snice 3.1.0 → 3.2.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 (217) hide show
  1. package/README.md +90 -41
  2. package/dist/components/accordion/snice-accordion-item.js +1 -1
  3. package/dist/components/accordion/snice-accordion-item.js.map +1 -1
  4. package/dist/components/accordion/snice-accordion.js +1 -1
  5. package/dist/components/accordion/snice-accordion.js.map +1 -1
  6. package/dist/components/alert/snice-alert.js +1 -1
  7. package/dist/components/alert/snice-alert.js.map +1 -1
  8. package/dist/components/avatar/snice-avatar.js +1 -1
  9. package/dist/components/avatar/snice-avatar.js.map +1 -1
  10. package/dist/components/badge/snice-badge.js +1 -1
  11. package/dist/components/badge/snice-badge.js.map +1 -1
  12. package/dist/components/banner/snice-banner.d.ts +22 -0
  13. package/dist/components/banner/snice-banner.js +180 -0
  14. package/dist/components/banner/snice-banner.js.map +1 -0
  15. package/dist/components/banner/snice-banner.types.d.ts +14 -0
  16. package/dist/components/breadcrumbs/snice-breadcrumbs.js +1 -1
  17. package/dist/components/breadcrumbs/snice-breadcrumbs.js.map +1 -1
  18. package/dist/components/button/snice-button.js +1 -1
  19. package/dist/components/button/snice-button.js.map +1 -1
  20. package/dist/components/card/snice-card.js +1 -1
  21. package/dist/components/card/snice-card.js.map +1 -1
  22. package/dist/components/checkbox/snice-checkbox.js +1 -1
  23. package/dist/components/checkbox/snice-checkbox.js.map +1 -1
  24. package/dist/components/chip/snice-chip.js +1 -1
  25. package/dist/components/chip/snice-chip.js.map +1 -1
  26. package/dist/components/color-display/snice-color-display.d.ts +14 -0
  27. package/dist/components/color-display/snice-color-display.js +151 -0
  28. package/dist/components/color-display/snice-color-display.js.map +1 -0
  29. package/dist/components/color-display/snice-color-display.types.d.ts +10 -0
  30. package/dist/components/color-picker/snice-color-picker.d.ts +50 -0
  31. package/dist/components/color-picker/snice-color-picker.js +489 -0
  32. package/dist/components/color-picker/snice-color-picker.js.map +1 -0
  33. package/dist/components/color-picker/snice-color-picker.types.d.ts +19 -0
  34. package/dist/components/date-picker/snice-date-picker.js +1 -1
  35. package/dist/components/date-picker/snice-date-picker.js.map +1 -1
  36. package/dist/components/divider/snice-divider.js +1 -1
  37. package/dist/components/divider/snice-divider.js.map +1 -1
  38. package/dist/components/drawer/snice-drawer.js +1 -1
  39. package/dist/components/drawer/snice-drawer.js.map +1 -1
  40. package/dist/components/empty-state/snice-empty-state.d.ts +13 -0
  41. package/dist/components/empty-state/snice-empty-state.js +121 -0
  42. package/dist/components/empty-state/snice-empty-state.js.map +1 -0
  43. package/dist/components/empty-state/snice-empty-state.types.d.ts +9 -0
  44. package/dist/components/file-upload/snice-file-upload.d.ts +45 -0
  45. package/dist/components/file-upload/snice-file-upload.js +394 -0
  46. package/dist/components/file-upload/snice-file-upload.js.map +1 -0
  47. package/dist/components/file-upload/snice-file-upload.types.d.ts +22 -0
  48. package/dist/components/image/snice-image.d.ts +22 -0
  49. package/dist/components/image/snice-image.js +201 -0
  50. package/dist/components/image/snice-image.js.map +1 -0
  51. package/dist/components/image/snice-image.types.d.ts +17 -0
  52. package/dist/components/input/snice-input.js +1 -1
  53. package/dist/components/input/snice-input.js.map +1 -1
  54. package/dist/components/kpi/snice-kpi.d.ts +16 -0
  55. package/dist/components/kpi/snice-kpi.js +162 -0
  56. package/dist/components/kpi/snice-kpi.js.map +1 -0
  57. package/dist/components/kpi/snice-kpi.types.d.ts +12 -0
  58. package/dist/components/layout/snice-layout-blog.js +1 -1
  59. package/dist/components/layout/snice-layout-blog.js.map +1 -1
  60. package/dist/components/layout/snice-layout-card.js +1 -1
  61. package/dist/components/layout/snice-layout-card.js.map +1 -1
  62. package/dist/components/layout/snice-layout-centered.js +1 -1
  63. package/dist/components/layout/snice-layout-centered.js.map +1 -1
  64. package/dist/components/layout/snice-layout-dashboard.js +1 -1
  65. package/dist/components/layout/snice-layout-dashboard.js.map +1 -1
  66. package/dist/components/layout/snice-layout-fullscreen.js +1 -1
  67. package/dist/components/layout/snice-layout-fullscreen.js.map +1 -1
  68. package/dist/components/layout/snice-layout-landing.js +1 -1
  69. package/dist/components/layout/snice-layout-landing.js.map +1 -1
  70. package/dist/components/layout/snice-layout-minimal.js +1 -1
  71. package/dist/components/layout/snice-layout-minimal.js.map +1 -1
  72. package/dist/components/layout/snice-layout-sidebar.js +1 -1
  73. package/dist/components/layout/snice-layout-sidebar.js.map +1 -1
  74. package/dist/components/layout/snice-layout-split.js +1 -1
  75. package/dist/components/layout/snice-layout-split.js.map +1 -1
  76. package/dist/components/layout/snice-layout.js +1 -1
  77. package/dist/components/layout/snice-layout.js.map +1 -1
  78. package/dist/components/link/snice-link.d.ts +13 -0
  79. package/dist/components/link/snice-link.js +137 -0
  80. package/dist/components/link/snice-link.js.map +1 -0
  81. package/dist/components/link/snice-link.types.d.ts +11 -0
  82. package/dist/components/login/snice-login.js +1 -1
  83. package/dist/components/login/snice-login.js.map +1 -1
  84. package/dist/components/modal/snice-modal.js +1 -1
  85. package/dist/components/modal/snice-modal.js.map +1 -1
  86. package/dist/components/nav/snice-nav.js +1 -1
  87. package/dist/components/nav/snice-nav.js.map +1 -1
  88. package/dist/components/progress/snice-progress.js +1 -1
  89. package/dist/components/progress/snice-progress.js.map +1 -1
  90. package/dist/components/radio/snice-radio.js +1 -1
  91. package/dist/components/radio/snice-radio.js.map +1 -1
  92. package/dist/components/select/snice-select.js +1 -1
  93. package/dist/components/select/snice-select.js.map +1 -1
  94. package/dist/components/skeleton/snice-skeleton.js +1 -1
  95. package/dist/components/skeleton/snice-skeleton.js.map +1 -1
  96. package/dist/components/slider/snice-slider.d.ts +53 -0
  97. package/dist/components/slider/snice-slider.js +479 -0
  98. package/dist/components/slider/snice-slider.js.map +1 -0
  99. package/dist/components/slider/snice-slider.types.d.ts +26 -0
  100. package/dist/components/snice-cell-C0slgOpe.js +4 -0
  101. package/dist/components/snice-cell-C0slgOpe.js.map +1 -0
  102. package/dist/components/sparkline/snice-sparkline.d.ts +21 -0
  103. package/dist/components/sparkline/snice-sparkline.js +228 -0
  104. package/dist/components/sparkline/snice-sparkline.js.map +1 -0
  105. package/dist/components/sparkline/snice-sparkline.types.d.ts +16 -0
  106. package/dist/components/spinner/snice-spinner.d.ts +10 -0
  107. package/dist/components/spinner/snice-spinner.js +109 -0
  108. package/dist/components/spinner/snice-spinner.js.map +1 -0
  109. package/dist/components/spinner/snice-spinner.types.d.ts +8 -0
  110. package/dist/components/stepper/snice-stepper-panel.d.ts +8 -0
  111. package/dist/components/stepper/snice-stepper-panel.js +70 -0
  112. package/dist/components/stepper/snice-stepper-panel.js.map +1 -0
  113. package/dist/components/stepper/snice-stepper-panel.types.d.ts +4 -0
  114. package/dist/components/stepper/snice-stepper.d.ts +15 -0
  115. package/dist/components/stepper/snice-stepper.js +163 -0
  116. package/dist/components/stepper/snice-stepper.js.map +1 -0
  117. package/dist/components/stepper/snice-stepper.types.d.ts +13 -0
  118. package/dist/components/switch/snice-switch.js +1 -1
  119. package/dist/components/switch/snice-switch.js.map +1 -1
  120. package/dist/components/table/snice-cell-actions.js +1 -1
  121. package/dist/components/table/snice-cell-actions.js.map +1 -1
  122. package/dist/components/table/snice-cell-boolean.js +1 -1
  123. package/dist/components/table/snice-cell-color.js +1 -1
  124. package/dist/components/table/snice-cell-color.js.map +1 -1
  125. package/dist/components/table/snice-cell-currency.js +1 -1
  126. package/dist/components/table/snice-cell-date.js +1 -1
  127. package/dist/components/table/snice-cell-duration.js +1 -1
  128. package/dist/components/table/snice-cell-email.js +1 -1
  129. package/dist/components/table/snice-cell-email.js.map +1 -1
  130. package/dist/components/table/snice-cell-filesize.js +1 -1
  131. package/dist/components/table/snice-cell-image.js +1 -1
  132. package/dist/components/table/snice-cell-image.js.map +1 -1
  133. package/dist/components/table/snice-cell-json.js +1 -1
  134. package/dist/components/table/snice-cell-json.js.map +1 -1
  135. package/dist/components/table/snice-cell-link.js +1 -1
  136. package/dist/components/table/snice-cell-link.js.map +1 -1
  137. package/dist/components/table/snice-cell-location.js +1 -1
  138. package/dist/components/table/snice-cell-location.js.map +1 -1
  139. package/dist/components/table/snice-cell-number.js +1 -1
  140. package/dist/components/table/snice-cell-percentage.js +1 -1
  141. package/dist/components/table/snice-cell-percentage.js.map +1 -1
  142. package/dist/components/table/snice-cell-phone.js +1 -1
  143. package/dist/components/table/snice-cell-phone.js.map +1 -1
  144. package/dist/components/table/snice-cell-progress.js +1 -1
  145. package/dist/components/table/snice-cell-rating.js +1 -1
  146. package/dist/components/table/snice-cell-sparkline.js +1 -1
  147. package/dist/components/table/snice-cell-status.js +1 -1
  148. package/dist/components/table/snice-cell-status.js.map +1 -1
  149. package/dist/components/table/snice-cell-tag.js +1 -1
  150. package/dist/components/table/snice-cell-tag.js.map +1 -1
  151. package/dist/components/table/snice-cell-text.js +1 -1
  152. package/dist/components/table/snice-cell.js +1 -1
  153. package/dist/components/table/snice-header.js +1 -1
  154. package/dist/components/table/snice-header.js.map +1 -1
  155. package/dist/components/table/snice-row.js +2 -2
  156. package/dist/components/table/snice-row.js.map +1 -1
  157. package/dist/components/table/snice-table.js +1 -1
  158. package/dist/components/tabs/snice-tab-panel.js +1 -1
  159. package/dist/components/tabs/snice-tab-panel.js.map +1 -1
  160. package/dist/components/tabs/snice-tab.js +1 -1
  161. package/dist/components/tabs/snice-tab.js.map +1 -1
  162. package/dist/components/tabs/snice-tabs.js +1 -1
  163. package/dist/components/tabs/snice-tabs.js.map +1 -1
  164. package/dist/components/textarea/snice-textarea.d.ts +52 -0
  165. package/dist/components/textarea/snice-textarea.js +407 -0
  166. package/dist/components/textarea/snice-textarea.js.map +1 -0
  167. package/dist/components/textarea/snice-textarea.types.d.ts +30 -0
  168. package/dist/components/timeline/snice-timeline.d.ts +11 -0
  169. package/dist/components/timeline/snice-timeline.js +112 -0
  170. package/dist/components/timeline/snice-timeline.js.map +1 -0
  171. package/dist/components/timeline/snice-timeline.types.d.ts +16 -0
  172. package/dist/components/tooltip/snice-tooltip.js +2 -2
  173. package/dist/components/tooltip/snice-tooltip.js.map +1 -1
  174. package/dist/index.cjs +125 -158
  175. package/dist/index.cjs.map +1 -1
  176. package/dist/index.esm.js +125 -158
  177. package/dist/index.esm.js.map +1 -1
  178. package/dist/index.iife.js +125 -158
  179. package/dist/index.iife.js.map +1 -1
  180. package/dist/parts.d.ts +13 -16
  181. package/dist/symbols.cjs +1 -1
  182. package/dist/symbols.esm.js +1 -1
  183. package/dist/template.d.ts +0 -1
  184. package/dist/transitions.cjs +1 -1
  185. package/dist/transitions.esm.js +1 -1
  186. package/docs/ai/README.md +10 -1
  187. package/docs/ai/components/banner.md +84 -0
  188. package/docs/ai/components/color-display.md +48 -0
  189. package/docs/ai/components/color-picker.md +75 -0
  190. package/docs/ai/components/empty-state.md +72 -0
  191. package/docs/ai/components/file-upload.md +93 -0
  192. package/docs/ai/components/image.md +60 -0
  193. package/docs/ai/components/kpi.md +158 -0
  194. package/docs/ai/components/link.md +77 -0
  195. package/docs/ai/components/slider.md +87 -0
  196. package/docs/ai/components/sparkline.md +168 -0
  197. package/docs/ai/components/spinner.md +47 -0
  198. package/docs/ai/components/stepper.md +216 -0
  199. package/docs/ai/components/textarea.md +87 -0
  200. package/docs/ai/components/timeline.md +77 -0
  201. package/docs/components/banner.md +106 -0
  202. package/docs/components/color-display.md +96 -0
  203. package/docs/components/color-picker.md +81 -0
  204. package/docs/components/empty-state.md +79 -0
  205. package/docs/components/file-upload.md +263 -0
  206. package/docs/components/image.md +110 -0
  207. package/docs/components/kpi.md +251 -0
  208. package/docs/components/link.md +229 -0
  209. package/docs/components/slider.md +297 -0
  210. package/docs/components/sparkline.md +293 -0
  211. package/docs/components/spinner.md +63 -0
  212. package/docs/components/stepper.md +410 -0
  213. package/docs/components/textarea.md +235 -0
  214. package/docs/components/timeline.md +192 -0
  215. package/package.json +2 -1
  216. package/dist/components/snice-cell-BLFVdxPp.js +0 -4
  217. package/dist/components/snice-cell-BLFVdxPp.js.map +0 -1
@@ -0,0 +1,79 @@
1
+ # Empty State Component
2
+
3
+ The `<snice-empty-state>` component provides a consistent way to display empty or no-data states.
4
+
5
+ ## Basic Usage
6
+
7
+ ```html
8
+ <snice-empty-state
9
+ icon="📭"
10
+ title="No data"
11
+ description="There's nothing here yet"
12
+ ></snice-empty-state>
13
+ ```
14
+
15
+ ## Properties
16
+
17
+ | Property | Type | Default | Description |
18
+ |----------|------|---------|-------------|
19
+ | `size` | `'small' \| 'medium' \| 'large'` | `'medium'` | Size variant |
20
+ | `icon` | `string` | `'📭'` | Icon (emoji or text) |
21
+ | `title` | `string` | `'No data'` | Title text |
22
+ | `description` | `string` | `''` | Description text |
23
+ | `actionText` | `string` | `''` | Action button text |
24
+ | `actionHref` | `string` | `''` | Action link URL |
25
+
26
+ ## Events
27
+
28
+ ### `@snice/empty-state-action`
29
+ Fired when action button/link is clicked.
30
+
31
+ ## Examples
32
+
33
+ ### No Search Results
34
+
35
+ ```html
36
+ <snice-empty-state
37
+ icon="🔍"
38
+ title="No results found"
39
+ description="Try adjusting your search criteria"
40
+ action-text="Clear Search"
41
+ ></snice-empty-state>
42
+ ```
43
+
44
+ ### Empty List
45
+
46
+ ```html
47
+ <snice-empty-state
48
+ icon="📦"
49
+ title="No items yet"
50
+ description="Get started by creating your first item"
51
+ action-text="Create Item"
52
+ ></snice-empty-state>
53
+ ```
54
+
55
+ ### 404 Page
56
+
57
+ ```html
58
+ <snice-empty-state
59
+ icon="🤷"
60
+ title="Page not found"
61
+ description="The page you're looking for doesn't exist"
62
+ action-text="Go Home"
63
+ action-href="/"
64
+ ></snice-empty-state>
65
+ ```
66
+
67
+ ### With Custom Content
68
+
69
+ ```html
70
+ <snice-empty-state
71
+ icon="🎨"
72
+ title="No projects"
73
+ >
74
+ <div slot="">
75
+ <button>Create Project</button>
76
+ <button>Import Project</button>
77
+ </div>
78
+ </snice-empty-state>
79
+ ```
@@ -0,0 +1,263 @@
1
+ # File Upload Component
2
+
3
+ The `<snice-file-upload>` component provides a file upload interface with drag-and-drop support, file previews, and validation.
4
+
5
+ ## Table of Contents
6
+ - [Basic Usage](#basic-usage)
7
+ - [Properties](#properties)
8
+ - [Methods](#methods)
9
+ - [Events](#events)
10
+ - [Features](#features)
11
+ - [Examples](#examples)
12
+
13
+ ## Basic Usage
14
+
15
+ ```html
16
+ <snice-file-upload
17
+ label="Upload Documents"
18
+ accept=".pdf,.doc,.docx"
19
+ max-size="5242880"
20
+ ></snice-file-upload>
21
+ ```
22
+
23
+ ```typescript
24
+ import 'snice/components/file-upload/snice-file-upload';
25
+
26
+ const upload = document.querySelector('snice-file-upload');
27
+ upload.addEventListener('@snice/file-upload-change', (e) => {
28
+ console.log('Files:', e.detail.files);
29
+ });
30
+ ```
31
+
32
+ ## Properties
33
+
34
+ | Property | Type | Default | Description |
35
+ |----------|------|---------|-------------|
36
+ | `size` | `'small' \| 'medium' \| 'large'` | `'medium'` | Size variant |
37
+ | `variant` | `'outlined' \| 'filled'` | `'outlined'` | Visual style variant |
38
+ | `accept` | `string` | `''` | Allowed file types (same as input accept) |
39
+ | `multiple` | `boolean` | `false` | Allow multiple file selection |
40
+ | `label` | `string` | `''` | Label text |
41
+ | `helperText` | `string` | `''` | Helper text below upload area |
42
+ | `errorText` | `string` | `''` | Error message (shown when invalid) |
43
+ | `disabled` | `boolean` | `false` | Whether upload is disabled |
44
+ | `required` | `boolean` | `false` | Whether upload is required |
45
+ | `invalid` | `boolean` | `false` | Whether to show invalid state |
46
+ | `maxSize` | `number` | `-1` | Maximum file size in bytes (-1 = no limit) |
47
+ | `maxFiles` | `number` | `-1` | Maximum number of files (-1 = no limit) |
48
+ | `name` | `string` | `''` | Form field name |
49
+ | `dragDrop` | `boolean` | `true` | Enable drag-and-drop |
50
+ | `showPreview` | `boolean` | `true` | Show image previews |
51
+ | `files` | `FileList \| null` | `null` | Selected files (read-only) |
52
+
53
+ ## Methods
54
+
55
+ ### `clear(): void`
56
+ Remove all selected files.
57
+
58
+ ```typescript
59
+ upload.clear();
60
+ ```
61
+
62
+ ### `removeFile(index: number): void`
63
+ Remove a specific file by index.
64
+
65
+ ```typescript
66
+ upload.removeFile(0); // Remove first file
67
+ ```
68
+
69
+ ## Events
70
+
71
+ ### `@snice/file-upload-change`
72
+ Fired when files are added or removed.
73
+
74
+ **Detail**: `{ files: File[], fileUpload: SniceFileUploadElement }`
75
+
76
+ ```typescript
77
+ upload.addEventListener('@snice/file-upload-change', (e) => {
78
+ console.log('Selected files:', e.detail.files);
79
+ e.detail.files.forEach(file => {
80
+ console.log(`- ${file.name} (${file.size} bytes)`);
81
+ });
82
+ });
83
+ ```
84
+
85
+ ### `@snice/file-upload-error`
86
+ Fired when file validation fails.
87
+
88
+ **Detail**: `{ message: string, fileUpload: SniceFileUploadElement }`
89
+
90
+ ```typescript
91
+ upload.addEventListener('@snice/file-upload-error', (e) => {
92
+ console.error('Upload error:', e.detail.message);
93
+ });
94
+ ```
95
+
96
+ ## Features
97
+
98
+ - **Drag and Drop**: Native drag-and-drop support with visual feedback
99
+ - **Image Preview**: Automatic thumbnail generation for image files
100
+ - **File Validation**: Size and type validation with error messaging
101
+ - **Multiple Files**: Support for single or multiple file selection
102
+ - **File Management**: Add and remove files before upload
103
+ - **Form Integration**: Form-associated custom element
104
+ - **Accessibility**: Full keyboard support and ARIA attributes
105
+
106
+ ## Examples
107
+
108
+ ### Basic Upload
109
+
110
+ ```html
111
+ <snice-file-upload
112
+ label="Upload File"
113
+ helper-text="Choose a file to upload"
114
+ ></snice-file-upload>
115
+ ```
116
+
117
+ ### Image Upload with Preview
118
+
119
+ ```html
120
+ <snice-file-upload
121
+ label="Upload Image"
122
+ accept="image/*"
123
+ max-size="2097152"
124
+ helper-text="Maximum 2MB, images only"
125
+ ></snice-file-upload>
126
+ ```
127
+
128
+ ### Multiple Files
129
+
130
+ ```html
131
+ <snice-file-upload
132
+ label="Upload Documents"
133
+ accept=".pdf,.doc,.docx"
134
+ multiple
135
+ max-files="5"
136
+ helper-text="Select up to 5 documents"
137
+ ></snice-file-upload>
138
+ ```
139
+
140
+ ### Without Drag-and-Drop
141
+
142
+ ```html
143
+ <snice-file-upload
144
+ label="Upload File"
145
+ drag-drop="false"
146
+ ></snice-file-upload>
147
+ ```
148
+
149
+ ### Different Sizes
150
+
151
+ ```html
152
+ <snice-file-upload size="small" label="Small"></snice-file-upload>
153
+ <snice-file-upload size="medium" label="Medium"></snice-file-upload>
154
+ <snice-file-upload size="large" label="Large"></snice-file-upload>
155
+ ```
156
+
157
+ ### Different Variants
158
+
159
+ ```html
160
+ <snice-file-upload variant="outlined" label="Outlined"></snice-file-upload>
161
+ <snice-file-upload variant="filled" label="Filled"></snice-file-upload>
162
+ ```
163
+
164
+ ### Error State
165
+
166
+ ```html
167
+ <snice-file-upload
168
+ label="Resume"
169
+ invalid
170
+ error-text="Please upload your resume"
171
+ required
172
+ ></snice-file-upload>
173
+ ```
174
+
175
+ ### File Type Restrictions
176
+
177
+ ```html
178
+ <!-- Images only -->
179
+ <snice-file-upload accept="image/*" label="Images"></snice-file-upload>
180
+
181
+ <!-- Specific formats -->
182
+ <snice-file-upload accept=".pdf,.doc,.docx" label="Documents"></snice-file-upload>
183
+
184
+ <!-- Multiple types -->
185
+ <snice-file-upload accept="image/*,.pdf" label="Images and PDFs"></snice-file-upload>
186
+ ```
187
+
188
+ ### With Size Validation
189
+
190
+ ```html
191
+ <snice-file-upload
192
+ label="Upload Photo"
193
+ accept="image/*"
194
+ max-size="5242880"
195
+ helper-text="Maximum 5MB"
196
+ ></snice-file-upload>
197
+
198
+ <script>
199
+ const upload = document.querySelector('snice-file-upload');
200
+ upload.addEventListener('@snice/file-upload-error', (e) => {
201
+ alert(e.detail.message);
202
+ });
203
+ </script>
204
+ ```
205
+
206
+ ### Form Integration
207
+
208
+ ```html
209
+ <form id="upload-form">
210
+ <snice-file-upload
211
+ name="documents"
212
+ label="Upload Documents"
213
+ accept=".pdf,.doc,.docx"
214
+ multiple
215
+ required
216
+ ></snice-file-upload>
217
+
218
+ <button type="submit">Submit</button>
219
+ </form>
220
+
221
+ <script>
222
+ document.getElementById('upload-form').addEventListener('submit', async (e) => {
223
+ e.preventDefault();
224
+
225
+ const formData = new FormData(e.target);
226
+ const files = formData.getAll('documents');
227
+
228
+ console.log(`Uploading ${files.length} file(s)...`);
229
+
230
+ // Upload to server
231
+ const response = await fetch('/api/upload', {
232
+ method: 'POST',
233
+ body: formData
234
+ });
235
+
236
+ console.log('Upload complete!');
237
+ });
238
+ </script>
239
+ ```
240
+
241
+ ### Managing Files Programmatically
242
+
243
+ ```html
244
+ <snice-file-upload id="file-upload" multiple></snice-file-upload>
245
+ <button onclick="clearFiles()">Clear All</button>
246
+ <button onclick="removeFirst()">Remove First</button>
247
+
248
+ <script>
249
+ const upload = document.getElementById('file-upload');
250
+
251
+ function clearFiles() {
252
+ upload.clear();
253
+ }
254
+
255
+ function removeFirst() {
256
+ upload.removeFile(0);
257
+ }
258
+
259
+ upload.addEventListener('@snice/file-upload-change', (e) => {
260
+ console.log(`${e.detail.files.length} file(s) selected`);
261
+ });
262
+ </script>
263
+ ```
@@ -0,0 +1,110 @@
1
+ # Image Component
2
+
3
+ The `<snice-image>` component provides a flexible image display with variants, sizes, lazy loading, and fallback support.
4
+
5
+ ## Basic Usage
6
+
7
+ ```html
8
+ <snice-image
9
+ src="https://example.com/image.jpg"
10
+ alt="Description"
11
+ ></snice-image>
12
+ ```
13
+
14
+ ## Properties
15
+
16
+ | Property | Type | Default | Description |
17
+ |----------|------|---------|-------------|
18
+ | `src` | `string` | `''` | Image source URL |
19
+ | `alt` | `string` | `''` | Alternative text |
20
+ | `fallback` | `string` | `''` | Fallback image URL on error |
21
+ | `variant` | `'rounded' \| 'square' \| 'circle'` | `'rounded'` | Shape variant |
22
+ | `size` | `'small' \| 'medium' \| 'large'` | `'medium'` | Predefined size |
23
+ | `lazy` | `boolean` | `true` | Enable lazy loading |
24
+ | `fit` | `'cover' \| 'contain' \| 'fill' \| 'none' \| 'scale-down'` | `'cover'` | Object-fit behavior |
25
+ | `width` | `string` | `''` | Custom width (CSS value) |
26
+ | `height` | `string` | `''` | Custom height (CSS value) |
27
+
28
+ ## Examples
29
+
30
+ ### Sizes
31
+
32
+ ```html
33
+ <snice-image src="image.jpg" size="small"></snice-image>
34
+ <snice-image src="image.jpg" size="medium"></snice-image>
35
+ <snice-image src="image.jpg" size="large"></snice-image>
36
+ ```
37
+
38
+ ### Shape Variants
39
+
40
+ ```html
41
+ <snice-image src="image.jpg" variant="rounded"></snice-image>
42
+ <snice-image src="image.jpg" variant="square"></snice-image>
43
+ <snice-image src="image.jpg" variant="circle"></snice-image>
44
+ ```
45
+
46
+ ### Object Fit
47
+
48
+ ```html
49
+ <snice-image src="image.jpg" fit="cover" width="200px" height="200px"></snice-image>
50
+ <snice-image src="image.jpg" fit="contain" width="200px" height="200px"></snice-image>
51
+ <snice-image src="image.jpg" fit="fill" width="200px" height="200px"></snice-image>
52
+ ```
53
+
54
+ ### Custom Dimensions
55
+
56
+ ```html
57
+ <snice-image src="image.jpg" width="300px" height="200px"></snice-image>
58
+ <snice-image src="image.jpg" width="100%" height="auto"></snice-image>
59
+ ```
60
+
61
+ ### Fallback Image
62
+
63
+ ```html
64
+ <snice-image
65
+ src="image.jpg"
66
+ fallback="placeholder.jpg"
67
+ alt="Profile picture"
68
+ ></snice-image>
69
+ ```
70
+
71
+ ### Lazy Loading
72
+
73
+ ```html
74
+ <!-- Lazy loaded (default) -->
75
+ <snice-image src="image.jpg"></snice-image>
76
+
77
+ <!-- Eager loaded -->
78
+ <snice-image src="image.jpg" lazy="false"></snice-image>
79
+ ```
80
+
81
+ ### Placeholder
82
+
83
+ ```html
84
+ <!-- Shows placeholder when no src -->
85
+ <snice-image variant="circle" size="medium"></snice-image>
86
+ ```
87
+
88
+ ## Styling
89
+
90
+ ```css
91
+ snice-image::part(container) {
92
+ /* Image container */
93
+ }
94
+
95
+ snice-image::part(image) {
96
+ /* The img element */
97
+ }
98
+
99
+ snice-image::part(placeholder) {
100
+ /* Placeholder element */
101
+ }
102
+ ```
103
+
104
+ ## Notes
105
+
106
+ - Images are lazy-loaded by default for better performance
107
+ - Placeholder is shown when `src` is empty
108
+ - Fallback image is used when main image fails to load
109
+ - Size presets provide consistent image dimensions
110
+ - Custom width/height override size presets
@@ -0,0 +1,251 @@
1
+ # KPI Component
2
+
3
+ A key performance indicator display component for showing metrics with optional trend visualization and sentiment indicators. Perfect for dashboards and analytics interfaces.
4
+
5
+ ## Features
6
+
7
+ - **Clear Value Display**: Large, prominent metric value
8
+ - **Trend Indicators**: Optional trend value with sentiment icons
9
+ - **Sparkline Integration**: Built-in sparkline chart support
10
+ - **Sentiment Colors**: Visual feedback with up/down/neutral states
11
+ - **Multiple Sizes**: Small, medium, and large variants
12
+ - **Flexible Layout**: Responsive and adaptable to different layouts
13
+
14
+ ## Basic Usage
15
+
16
+ ```html
17
+ <snice-kpi
18
+ label="Total Revenue"
19
+ value="$45,231">
20
+ </snice-kpi>
21
+ ```
22
+
23
+ ## Properties
24
+
25
+ | Property | Type | Default | Description |
26
+ |----------|------|---------|-------------|
27
+ | `label` | `string` | `''` | Label text (metric name) |
28
+ | `value` | `string \| number` | `''` | Main metric value to display |
29
+ | `trend-value` | `string \| number` | `undefined` | Optional trend value (e.g., "+12.5%") |
30
+ | `trend-data` | `number[]` | `undefined` | Data for sparkline chart |
31
+ | `sentiment` | `KpiSentiment` | `undefined` | Trend sentiment ('up', 'down', 'neutral') |
32
+ | `size` | `KpiSize` | `'medium'` | Component size ('small', 'medium', 'large') |
33
+ | `show-sparkline` | `boolean` | `true` | Whether to show sparkline when data is provided |
34
+
35
+ ## With Trend Indicator
36
+
37
+ ```html
38
+ <snice-kpi
39
+ label="Monthly Revenue"
40
+ value="$54,239"
41
+ trend-value="+12.5%"
42
+ sentiment="up">
43
+ </snice-kpi>
44
+ ```
45
+
46
+ ## With Sparkline
47
+
48
+ ```html
49
+ <snice-kpi
50
+ id="sales"
51
+ label="Weekly Sales"
52
+ value="$28,450"
53
+ trend-value="+15.3%"
54
+ sentiment="up">
55
+ </snice-kpi>
56
+
57
+ <script>
58
+ document.getElementById('sales').trendData = [
59
+ 20, 25, 22, 30, 28, 35, 32, 38, 36, 42, 40, 45, 43, 48
60
+ ];
61
+ </script>
62
+ ```
63
+
64
+ ## Sentiment Variants
65
+
66
+ ### Up (Positive)
67
+ ```html
68
+ <snice-kpi
69
+ label="Profit Margin"
70
+ value="34.2%"
71
+ trend-value="+3.5%"
72
+ sentiment="up">
73
+ </snice-kpi>
74
+ ```
75
+
76
+ ### Down (Attention Needed)
77
+ ```html
78
+ <snice-kpi
79
+ label="Churn Rate"
80
+ value="2.3%"
81
+ trend-value="+0.8%"
82
+ sentiment="down">
83
+ </snice-kpi>
84
+ ```
85
+
86
+ ### Neutral (Stable)
87
+ ```html
88
+ <snice-kpi
89
+ label="Market Share"
90
+ value="28.5%"
91
+ trend-value="±0%"
92
+ sentiment="neutral">
93
+ </snice-kpi>
94
+ ```
95
+
96
+ ## Sizes
97
+
98
+ ### Small
99
+ ```html
100
+ <snice-kpi
101
+ label="Active Users"
102
+ value="1,234"
103
+ size="small">
104
+ </snice-kpi>
105
+ ```
106
+
107
+ ### Medium (Default)
108
+ ```html
109
+ <snice-kpi
110
+ label="Active Users"
111
+ value="1,234"
112
+ size="medium">
113
+ </snice-kpi>
114
+ ```
115
+
116
+ ### Large
117
+ ```html
118
+ <snice-kpi
119
+ label="Active Users"
120
+ value="1,234"
121
+ size="large">
122
+ </snice-kpi>
123
+ ```
124
+
125
+ ## CSS Parts
126
+
127
+ Use `::part()` to style internal elements:
128
+
129
+ ```css
130
+ snice-kpi::part(container) {
131
+ border: 2px solid #e0e0e0;
132
+ }
133
+
134
+ snice-kpi::part(label) {
135
+ text-transform: uppercase;
136
+ }
137
+
138
+ snice-kpi::part(value) {
139
+ color: #2563eb;
140
+ }
141
+
142
+ snice-kpi::part(trend) {
143
+ font-weight: 700;
144
+ }
145
+ ```
146
+
147
+ ## Theming
148
+
149
+ The component uses these CSS custom properties:
150
+
151
+ ```css
152
+ --snice-color-background
153
+ --snice-color-border
154
+ --snice-color-text
155
+ --snice-color-text-secondary
156
+ --snice-color-success
157
+ --snice-color-danger
158
+ --snice-spacing-*
159
+ --snice-font-size-*
160
+ --snice-font-weight-*
161
+ --snice-border-radius-md
162
+ ```
163
+
164
+ ## Examples
165
+
166
+ ### Dashboard Metrics
167
+ ```html
168
+ <div style="display: grid; grid-template-columns: repeat(3, 1fr); gap: 20px;">
169
+ <snice-kpi
170
+ id="revenue"
171
+ label="Monthly Revenue"
172
+ value="$127,450"
173
+ trend-value="+22.4%"
174
+ sentiment="up">
175
+ </snice-kpi>
176
+
177
+ <snice-kpi
178
+ id="users"
179
+ label="Active Users"
180
+ value="2,345"
181
+ trend-value="+8.7%"
182
+ sentiment="up">
183
+ </snice-kpi>
184
+
185
+ <snice-kpi
186
+ id="conversion"
187
+ label="Conversion Rate"
188
+ value="3.24%"
189
+ trend-value="-0.5%"
190
+ sentiment="down">
191
+ </snice-kpi>
192
+ </div>
193
+
194
+ <script>
195
+ document.getElementById('revenue').trendData = [20, 25, 30, 28, 35, 40, 45];
196
+ document.getElementById('users').trendData = [100, 120, 110, 150, 140, 170, 160];
197
+ document.getElementById('conversion').trendData = [3.5, 3.3, 3.4, 3.2, 3.3, 3.1, 3.24];
198
+ </script>
199
+ ```
200
+
201
+ ### Without Sparkline
202
+ ```html
203
+ <snice-kpi
204
+ label="Customer Satisfaction"
205
+ value="4.8/5"
206
+ trend-value="+0.2"
207
+ sentiment="up"
208
+ show-sparkline="false">
209
+ </snice-kpi>
210
+ ```
211
+
212
+ ### Complex Metrics
213
+ ```html
214
+ <snice-kpi
215
+ id="nps"
216
+ label="Net Promoter Score"
217
+ value="72"
218
+ trend-value="+4 pts"
219
+ sentiment="up">
220
+ </snice-kpi>
221
+
222
+ <snice-kpi
223
+ id="cac"
224
+ label="Customer Acquisition Cost"
225
+ value="$156"
226
+ trend-value="-5.2%"
227
+ sentiment="down">
228
+ </snice-kpi>
229
+ ```
230
+
231
+ ## Best Practices
232
+
233
+ 1. **Use Clear Labels**: Make metric names concise and understandable
234
+ 2. **Format Values**: Present numbers in a readable format ($45K vs $45231.50)
235
+ 3. **Consistent Sentiment**: Use 'down' for bad news even if the number decreased (e.g., costs going down is good, but use 'down' for the direction)
236
+ 4. **Group Related KPIs**: Display related metrics together for context
237
+ 5. **Update Regularly**: Keep metrics fresh with real-time or frequent updates
238
+
239
+ ## Accessibility
240
+
241
+ - Labels provide context for screen readers
242
+ - Sentiment indicators have clear visual differentiation
243
+ - Sufficient color contrast for all text elements
244
+ - Keyboard navigation supported through standard focus
245
+
246
+ ## Performance
247
+
248
+ - Lightweight component with minimal DOM
249
+ - Efficient sparkline rendering via SVG
250
+ - CSS containment for optimized rendering
251
+ - No external dependencies beyond sparkline component