snice 1.14.3 → 2.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (185) hide show
  1. package/bin/templates/base/tsconfig.json +5 -4
  2. package/components/accordion/demo.html +403 -0
  3. package/components/accordion/snice-accordion-item.css +85 -0
  4. package/components/accordion/snice-accordion-item.ts +226 -0
  5. package/components/accordion/snice-accordion.css +31 -0
  6. package/components/accordion/snice-accordion.ts +182 -0
  7. package/components/accordion/snice-accordion.types.ts +32 -0
  8. package/components/alert/demo.html +445 -0
  9. package/components/alert/snice-alert.css +195 -0
  10. package/components/alert/snice-alert.ts +141 -0
  11. package/components/alert/snice-alert.types.ts +12 -0
  12. package/components/avatar/demo.html +598 -0
  13. package/components/avatar/snice-avatar.css +131 -0
  14. package/components/avatar/snice-avatar.ts +136 -0
  15. package/components/avatar/snice-avatar.types.ts +13 -0
  16. package/components/badge/demo.html +523 -0
  17. package/components/badge/snice-badge.css +161 -0
  18. package/components/badge/snice-badge.ts +117 -0
  19. package/components/badge/snice-badge.types.ts +16 -0
  20. package/components/breadcrumbs/demo.html +404 -0
  21. package/components/breadcrumbs/snice-breadcrumbs.css +133 -0
  22. package/components/breadcrumbs/snice-breadcrumbs.ts +191 -0
  23. package/components/breadcrumbs/snice-breadcrumbs.types.ts +26 -0
  24. package/components/breadcrumbs/snice-crumb.ts +26 -0
  25. package/components/button/demo.html +42 -0
  26. package/components/button/snice-button.css +230 -0
  27. package/components/button/snice-button.ts +169 -0
  28. package/components/button/snice-button.types.ts +25 -0
  29. package/components/card/demo.html +525 -0
  30. package/components/card/snice-card.css +140 -0
  31. package/components/card/snice-card.ts +102 -0
  32. package/components/card/snice-card.types.ts +10 -0
  33. package/components/checkbox/demo.html +253 -0
  34. package/components/checkbox/snice-checkbox.css +164 -0
  35. package/components/checkbox/snice-checkbox.ts +223 -0
  36. package/components/checkbox/snice-checkbox.types.ts +22 -0
  37. package/components/chip/demo.html +383 -0
  38. package/components/chip/snice-chip.css +195 -0
  39. package/components/chip/snice-chip.ts +139 -0
  40. package/components/chip/snice-chip.types.ts +15 -0
  41. package/components/date-picker/README.md +233 -0
  42. package/components/date-picker/demo.html +191 -0
  43. package/components/date-picker/snice-date-picker.css +330 -0
  44. package/components/date-picker/snice-date-picker.ts +777 -0
  45. package/components/date-picker/snice-date-picker.types.ts +83 -0
  46. package/components/divider/demo.html +233 -0
  47. package/components/divider/snice-divider.css +155 -0
  48. package/components/divider/snice-divider.ts +69 -0
  49. package/components/divider/snice-divider.types.ts +15 -0
  50. package/components/drawer/demo.html +328 -0
  51. package/components/drawer/snice-drawer.css +476 -0
  52. package/components/drawer/snice-drawer.ts +287 -0
  53. package/components/drawer/snice-drawer.types.ts +17 -0
  54. package/components/global.d.ts +14 -0
  55. package/components/input/demo.html +303 -0
  56. package/components/input/snice-input.css +257 -0
  57. package/components/input/snice-input.ts +442 -0
  58. package/components/input/snice-input.types.ts +59 -0
  59. package/components/input/test.html +77 -0
  60. package/components/layout/README.md +260 -0
  61. package/components/layout/demo.html +538 -0
  62. package/components/layout/snice-layout-blog.css +129 -0
  63. package/components/layout/snice-layout-blog.ts +48 -0
  64. package/components/layout/snice-layout-card.css +104 -0
  65. package/components/layout/snice-layout-card.ts +35 -0
  66. package/components/layout/snice-layout-centered.css +51 -0
  67. package/components/layout/snice-layout-centered.ts +22 -0
  68. package/components/layout/snice-layout-dashboard.css +98 -0
  69. package/components/layout/snice-layout-dashboard.ts +45 -0
  70. package/components/layout/snice-layout-fullscreen.css +72 -0
  71. package/components/layout/snice-layout-fullscreen.ts +34 -0
  72. package/components/layout/snice-layout-landing.css +92 -0
  73. package/components/layout/snice-layout-landing.ts +47 -0
  74. package/components/layout/snice-layout-minimal.css +16 -0
  75. package/components/layout/snice-layout-minimal.ts +19 -0
  76. package/components/layout/snice-layout-sidebar.css +117 -0
  77. package/components/layout/snice-layout-sidebar.ts +48 -0
  78. package/components/layout/snice-layout-split.css +103 -0
  79. package/components/layout/snice-layout-split.ts +29 -0
  80. package/components/layout/snice-layout.css +72 -0
  81. package/components/layout/snice-layout.ts +35 -0
  82. package/components/layout/snice-layout.types.ts +5 -0
  83. package/components/login/demo-auth-controller.ts +185 -0
  84. package/components/login/demo.html +470 -0
  85. package/components/login/snice-login.css +204 -0
  86. package/components/login/snice-login.ts +337 -0
  87. package/components/login/snice-login.types.ts +34 -0
  88. package/components/modal/demo.html +291 -0
  89. package/components/modal/snice-modal.css +203 -0
  90. package/components/modal/snice-modal.ts +233 -0
  91. package/components/modal/snice-modal.types.ts +21 -0
  92. package/components/pagination/demo.html +395 -0
  93. package/components/pagination/snice-pagination.ts +333 -0
  94. package/components/pagination/snice-pagination.types.ts +21 -0
  95. package/components/progress/demo.html +510 -0
  96. package/components/progress/snice-progress.css +267 -0
  97. package/components/progress/snice-progress.ts +247 -0
  98. package/components/progress/snice-progress.types.ts +19 -0
  99. package/components/radio/demo.html +287 -0
  100. package/components/radio/snice-radio.css +171 -0
  101. package/components/radio/snice-radio.ts +218 -0
  102. package/components/radio/snice-radio.types.ts +21 -0
  103. package/components/select/demo.html +511 -0
  104. package/components/select/snice-option.ts +52 -0
  105. package/components/select/snice-option.types.ts +14 -0
  106. package/components/select/snice-select.css +392 -0
  107. package/components/select/snice-select.ts +796 -0
  108. package/components/select/snice-select.types.ts +55 -0
  109. package/components/skeleton/demo.html +514 -0
  110. package/components/skeleton/snice-skeleton.css +109 -0
  111. package/components/skeleton/snice-skeleton.ts +126 -0
  112. package/components/skeleton/snice-skeleton.types.ts +11 -0
  113. package/components/switch/demo.html +284 -0
  114. package/components/switch/snice-switch.css +221 -0
  115. package/components/switch/snice-switch.ts +229 -0
  116. package/components/switch/snice-switch.types.ts +23 -0
  117. package/components/symbols.ts +23 -0
  118. package/components/table/demo-table-controller.ts +100 -0
  119. package/components/table/demo.html +480 -0
  120. package/components/table/snice-cell-boolean.ts +112 -0
  121. package/components/table/snice-cell-date.ts +210 -0
  122. package/components/table/snice-cell-duration.ts +91 -0
  123. package/components/table/snice-cell-filesize.ts +90 -0
  124. package/components/table/snice-cell-number.ts +165 -0
  125. package/components/table/snice-cell-progress.ts +83 -0
  126. package/components/table/snice-cell-rating.ts +82 -0
  127. package/components/table/snice-cell-sparkline.ts +253 -0
  128. package/components/table/snice-cell-text.ts +125 -0
  129. package/components/table/snice-cell.css +296 -0
  130. package/components/table/snice-cell.ts +473 -0
  131. package/components/table/snice-column.ts +353 -0
  132. package/components/table/snice-header.css +243 -0
  133. package/components/table/snice-header.ts +261 -0
  134. package/components/table/snice-progress.ts +66 -0
  135. package/components/table/snice-rating.ts +45 -0
  136. package/components/table/snice-row.css +255 -0
  137. package/components/table/snice-row.ts +331 -0
  138. package/components/table/snice-table.css +241 -0
  139. package/components/table/snice-table.ts +737 -0
  140. package/components/table/snice-table.types.ts +158 -0
  141. package/components/tabs/demo.html +487 -0
  142. package/components/tabs/snice-tab-panel.css +264 -0
  143. package/components/tabs/snice-tab-panel.ts +47 -0
  144. package/components/tabs/snice-tab.css +96 -0
  145. package/components/tabs/snice-tab.ts +65 -0
  146. package/components/tabs/snice-tabs.css +189 -0
  147. package/components/tabs/snice-tabs.ts +332 -0
  148. package/components/tabs/snice-tabs.types.ts +28 -0
  149. package/components/theme/theme.css +234 -0
  150. package/components/toast/demo.html +329 -0
  151. package/components/toast/snice-toast-container.ts +256 -0
  152. package/components/toast/snice-toast.css +213 -0
  153. package/components/toast/snice-toast.ts +276 -0
  154. package/components/toast/snice-toast.types.ts +35 -0
  155. package/components/tooltip/demo.html +350 -0
  156. package/components/tooltip/snice-tooltip-portal.css +79 -0
  157. package/components/tooltip/snice-tooltip.css +117 -0
  158. package/components/tooltip/snice-tooltip.ts +612 -0
  159. package/components/tooltip/snice-tooltip.types.ts +32 -0
  160. package/components/transitions.ts +94 -0
  161. package/components/tsconfig.json +18 -0
  162. package/dist/index.cjs +441 -329
  163. package/dist/index.cjs.map +1 -1
  164. package/dist/index.cjs.min.map +1 -1
  165. package/dist/index.esm.js +441 -329
  166. package/dist/index.esm.js.map +1 -1
  167. package/dist/index.esm.min.js +3 -3
  168. package/dist/index.esm.min.js.map +1 -1
  169. package/dist/index.iife.js +441 -329
  170. package/dist/index.iife.js.map +1 -1
  171. package/dist/index.iife.min.js +3 -3
  172. package/dist/index.iife.min.js.map +1 -1
  173. package/dist/symbols.esm.js +1 -1
  174. package/dist/transitions.esm.js +1 -1
  175. package/dist/types/controller.d.ts +1 -1
  176. package/dist/types/element.d.ts +10 -10
  177. package/dist/types/events.d.ts +2 -2
  178. package/dist/types/index.d.ts +1 -1
  179. package/dist/types/observe.d.ts +1 -1
  180. package/dist/types/request-response.d.ts +2 -3
  181. package/dist/types/router.d.ts +1 -1
  182. package/package.json +9 -3
  183. package/dist/index.cjs.min +0 -15
  184. package/dist/symbols.cjs +0 -103
  185. package/dist/transitions.cjs +0 -219
@@ -0,0 +1,267 @@
1
+ :host {
2
+ --progress-height: 0.5rem; /* 8px */
3
+ --progress-radius: 4px;
4
+ --progress-bg: #e5e7eb;
5
+ --progress-color: #3b82f6;
6
+ --progress-animation-duration: 1.5s;
7
+
8
+ display: inline-block;
9
+ width: 100%;
10
+ }
11
+
12
+ :host([variant="circular"]) {
13
+ width: auto;
14
+ }
15
+
16
+ /* Linear Progress Bar */
17
+ .progress {
18
+ position: relative;
19
+ width: 100%;
20
+ background: var(--progress-bg);
21
+ border-radius: var(--progress-radius);
22
+ overflow: hidden;
23
+ }
24
+
25
+ .progress--linear {
26
+ height: var(--progress-height);
27
+ }
28
+
29
+ .progress__bar {
30
+ height: 100%;
31
+ background: var(--progress-color);
32
+ border-radius: var(--progress-radius);
33
+ transition: width 0.3s ease;
34
+ position: relative;
35
+ overflow: hidden;
36
+ }
37
+
38
+ /* Sizes */
39
+ :host([size="small"]) {
40
+ --progress-height: 0.25rem; /* 4px */
41
+ --progress-spinner-size: 1.5rem; /* 24px */
42
+ --progress-spinner-stroke: 3px;
43
+ }
44
+
45
+ :host([size="medium"]) {
46
+ --progress-height: 0.5rem; /* 8px */
47
+ --progress-spinner-size: 2.5rem; /* 40px */
48
+ --progress-spinner-stroke: 4px;
49
+ }
50
+
51
+ :host([size="large"]) {
52
+ --progress-height: 0.75rem; /* 12px */
53
+ --progress-spinner-size: 3.5rem; /* 56px */
54
+ --progress-spinner-stroke: 5px;
55
+ }
56
+
57
+ :host([size="xl"]) {
58
+ --progress-height: 1rem; /* 16px */
59
+ --progress-spinner-size: 5rem; /* 80px */
60
+ --progress-spinner-stroke: 6px;
61
+ }
62
+
63
+ :host([size="xxl"]) {
64
+ --progress-height: 1.25rem; /* 20px */
65
+ --progress-spinner-size: 7.5rem; /* 120px */
66
+ --progress-spinner-stroke: 8px;
67
+ }
68
+
69
+ :host([size="xxxl"]) {
70
+ --progress-height: 1.5rem; /* 24px */
71
+ --progress-spinner-size: 10rem; /* 160px */
72
+ --progress-spinner-stroke: 10px;
73
+ }
74
+
75
+ /* Colors */
76
+ :host([color="primary"]) {
77
+ --progress-color: #3b82f6;
78
+ }
79
+
80
+ :host([color="success"]) {
81
+ --progress-color: #10b981;
82
+ }
83
+
84
+ :host([color="warning"]) {
85
+ --progress-color: #f59e0b;
86
+ }
87
+
88
+ :host([color="error"]) {
89
+ --progress-color: #ef4444;
90
+ }
91
+
92
+ :host([color="info"]) {
93
+ --progress-color: #6366f1;
94
+ }
95
+
96
+ /* Striped Pattern */
97
+ :host([striped]) .progress__bar::after {
98
+ content: '';
99
+ position: absolute;
100
+ top: 0;
101
+ left: 0;
102
+ right: 0;
103
+ bottom: 0;
104
+ background-image: linear-gradient(
105
+ 45deg,
106
+ rgba(255, 255, 255, 0.15) 25%,
107
+ transparent 25%,
108
+ transparent 50%,
109
+ rgba(255, 255, 255, 0.15) 50%,
110
+ rgba(255, 255, 255, 0.15) 75%,
111
+ transparent 75%,
112
+ transparent
113
+ );
114
+ background-size: 1rem 1rem;
115
+ }
116
+
117
+ /* Animated Stripes */
118
+ :host([animated]) .progress__bar::after {
119
+ animation: progress-stripes var(--progress-animation-duration) linear infinite;
120
+ }
121
+
122
+ @keyframes progress-stripes {
123
+ from {
124
+ background-position: 1rem 0;
125
+ }
126
+ to {
127
+ background-position: 0 0;
128
+ }
129
+ }
130
+
131
+ /* Indeterminate State */
132
+ :host([indeterminate]) .progress__bar {
133
+ width: 30% !important;
134
+ animation: progress-indeterminate var(--progress-animation-duration) ease-in-out infinite;
135
+ }
136
+
137
+ @keyframes progress-indeterminate {
138
+ 0% {
139
+ transform: translateX(-100%);
140
+ }
141
+ 100% {
142
+ transform: translateX(400%);
143
+ }
144
+ }
145
+
146
+ /* Label */
147
+ .progress__label {
148
+ position: absolute;
149
+ top: 50%;
150
+ left: 50%;
151
+ transform: translate(-50%, -50%);
152
+ font-size: 0.75rem;
153
+ font-weight: 600;
154
+ color: white;
155
+ text-shadow: 0 0 2px rgba(0, 0, 0, 0.3);
156
+ white-space: nowrap;
157
+ z-index: 1;
158
+ }
159
+
160
+ .progress--with-label {
161
+ height: calc(var(--progress-height) + 0.5rem); /* +8px */
162
+ min-height: 1.25rem; /* 20px */
163
+ }
164
+
165
+ /* Circular Progress */
166
+ .progress--circular {
167
+ display: inline-block;
168
+ width: var(--progress-spinner-size, 2.5rem); /* 40px */
169
+ height: var(--progress-spinner-size, 2.5rem); /* 40px */
170
+ position: relative;
171
+ background: transparent;
172
+ }
173
+
174
+ .progress__circle {
175
+ transform: rotate(-90deg);
176
+ width: 100%;
177
+ height: 100%;
178
+ background: transparent;
179
+ shape-rendering: geometricPrecision;
180
+ }
181
+
182
+ .progress__circle-bg,
183
+ .progress__circle-bar {
184
+ fill: none;
185
+ stroke-width: var(--progress-spinner-stroke, 4px);
186
+ shape-rendering: geometricPrecision;
187
+ vector-effect: non-scaling-stroke;
188
+ }
189
+
190
+ .progress__circle-bg {
191
+ stroke: var(--progress-bg);
192
+ opacity: 0.2;
193
+ }
194
+
195
+ .progress__circle-bar {
196
+ stroke: var(--progress-color);
197
+ stroke-linecap: round;
198
+ transition: stroke-dashoffset 0.3s ease;
199
+ }
200
+
201
+ /* Circular Indeterminate */
202
+ :host([variant="circular"][indeterminate]) .progress__circle {
203
+ animation: progress-rotate 2s linear infinite;
204
+ }
205
+
206
+ :host([variant="circular"][indeterminate]) .progress__circle-bar {
207
+ animation: progress-dash 1.5s ease-in-out infinite;
208
+ }
209
+
210
+ @keyframes progress-rotate {
211
+ 100% {
212
+ transform: rotate(270deg);
213
+ }
214
+ }
215
+
216
+ @keyframes progress-dash {
217
+ 0% {
218
+ stroke-dasharray: 1, 150;
219
+ stroke-dashoffset: 0;
220
+ }
221
+ 50% {
222
+ stroke-dasharray: 90, 150;
223
+ stroke-dashoffset: -35;
224
+ }
225
+ 100% {
226
+ stroke-dasharray: 90, 150;
227
+ stroke-dashoffset: -124;
228
+ }
229
+ }
230
+
231
+ /* Circular Label */
232
+ .progress__circle-label {
233
+ position: absolute;
234
+ top: 50%;
235
+ left: 50%;
236
+ transform: translate(-50%, -50%);
237
+ font-size: 0.625rem; /* Default medium size */
238
+ font-weight: 600;
239
+ color: var(--progress-color);
240
+ -webkit-font-smoothing: antialiased;
241
+ -moz-osx-font-smoothing: grayscale;
242
+ }
243
+
244
+ /* Adjust label size for different sizes */
245
+ :host([size="small"]) .progress__circle-label {
246
+ font-size: 0.375rem;
247
+ }
248
+
249
+ :host([size="medium"]) .progress__circle-label {
250
+ font-size: 0.625rem;
251
+ }
252
+
253
+ :host([size="large"]) .progress__circle-label {
254
+ font-size: 1rem;
255
+ }
256
+
257
+ :host([size="xl"]) .progress__circle-label {
258
+ font-size: 1.25rem;
259
+ }
260
+
261
+ :host([size="xxl"]) .progress__circle-label {
262
+ font-size: 1.75rem;
263
+ }
264
+
265
+ :host([size="xxxl"]) .progress__circle-label {
266
+ font-size: 2.25rem;
267
+ }
@@ -0,0 +1,247 @@
1
+ import { element, property, watch, ready, query, dispatch } from 'snice';
2
+ import css from './snice-progress.css?inline';
3
+ import type { ProgressVariant, ProgressSize, ProgressColor, SniceProgressElement } from './snice-progress.types';
4
+
5
+ @element('snice-progress')
6
+ export class SniceProgress extends HTMLElement implements SniceProgressElement {
7
+ @property({ type: Number, reflect: true })
8
+ value = 0;
9
+
10
+ @property({ type: Number, reflect: true })
11
+ max = 100;
12
+
13
+ @property({ reflect: true })
14
+ variant: ProgressVariant = 'linear';
15
+
16
+ @property({ reflect: true })
17
+ size: ProgressSize = 'medium';
18
+
19
+ @property({ reflect: true })
20
+ color: ProgressColor = 'primary';
21
+
22
+ @property({ type: Boolean, reflect: true })
23
+ indeterminate = false;
24
+
25
+ @property({ type: Boolean, attribute: 'show-label', reflect: true })
26
+ showLabel = false;
27
+
28
+ @property({ reflect: true })
29
+ label = '';
30
+
31
+ @property({ type: Boolean, reflect: true })
32
+ striped = false;
33
+
34
+ @property({ type: Boolean, reflect: true })
35
+ animated = false;
36
+
37
+ @property({ type: Number, reflect: true })
38
+ thickness = 4;
39
+
40
+ @query('.progress__bar')
41
+ progressBar?: HTMLElement;
42
+
43
+ @query('.progress__circle-bar')
44
+ circleBar?: SVGCircleElement;
45
+
46
+ @query('.progress__label')
47
+ labelElement?: HTMLElement;
48
+
49
+ @query('.progress__circle-label')
50
+ circleLabelElement?: HTMLElement;
51
+
52
+ private radius = 0;
53
+ private circumference = 0;
54
+
55
+ html() {
56
+ if (this.variant === 'circular') {
57
+ return this.renderCircular();
58
+ }
59
+ return this.renderLinear();
60
+ }
61
+
62
+ css() {
63
+ return css;
64
+ }
65
+
66
+ private renderLinear() {
67
+ const percentage = this.getPercentage();
68
+ const labelText = this.label || `${Math.round(percentage)}%`;
69
+
70
+ return /*html*/`
71
+ <div class="progress progress--linear ${this.showLabel ? 'progress--with-label' : ''}"
72
+ role="progressbar"
73
+ aria-valuenow="${this.value}"
74
+ aria-valuemin="0"
75
+ aria-valuemax="${this.max}"
76
+ aria-label="${labelText}">
77
+ <div class="progress__bar" style="width: ${this.indeterminate ? '' : percentage + '%'}">
78
+ ${this.showLabel ? /*html*/`
79
+ <span class="progress__label">${labelText}</span>
80
+ ` : ''}
81
+ </div>
82
+ </div>
83
+ `;
84
+ }
85
+
86
+ private renderCircular() {
87
+ const size = this.getSizeValue();
88
+ const strokeWidth = this.thickness;
89
+ const radius = (size - strokeWidth * 2) / 2;
90
+ const circumference = radius * 2 * Math.PI;
91
+ const percentage = this.getPercentage();
92
+ const offset = this.indeterminate ? 0 : circumference - (percentage / 100) * circumference;
93
+ const labelText = this.label || `${Math.round(percentage)}%`;
94
+
95
+ this.radius = radius;
96
+ this.circumference = circumference;
97
+
98
+ return /*html*/`
99
+ <div class="progress progress--circular"
100
+ role="progressbar"
101
+ aria-valuenow="${this.value}"
102
+ aria-valuemin="0"
103
+ aria-valuemax="${this.max}"
104
+ aria-label="${labelText}">
105
+ <svg class="progress__circle" viewBox="0 0 ${size} ${size}">
106
+ <circle
107
+ class="progress__circle-bg"
108
+ cx="${size / 2}"
109
+ cy="${size / 2}"
110
+ r="${radius}"
111
+ />
112
+ <circle
113
+ class="progress__circle-bar"
114
+ cx="${size / 2}"
115
+ cy="${size / 2}"
116
+ r="${radius}"
117
+ stroke-dasharray="${circumference}"
118
+ stroke-dashoffset="${offset}"
119
+ />
120
+ </svg>
121
+ ${this.showLabel && !this.indeterminate ? /*html*/`
122
+ <div class="progress__circle-label">${labelText}</div>
123
+ ` : ''}
124
+ </div>
125
+ `;
126
+ }
127
+
128
+ @ready()
129
+ init() {
130
+ this.updateProgress();
131
+ }
132
+
133
+ @watch('value', 'max', 'indeterminate')
134
+ handleProgressChange() {
135
+ this.updateProgress();
136
+ this.dispatchProgressChange();
137
+ }
138
+
139
+ @watch('variant')
140
+ handleVariantChange() {
141
+ // Re-render when variant changes
142
+ const shadow = this.shadowRoot;
143
+ if (shadow) {
144
+ shadow.innerHTML = '';
145
+ if (this.css) {
146
+ const style = document.createElement('style');
147
+ style.textContent = this.css();
148
+ shadow.appendChild(style);
149
+ }
150
+ const template = document.createElement('template');
151
+ template.innerHTML = this.html();
152
+ shadow.appendChild(template.content.cloneNode(true));
153
+
154
+ // Re-query elements after re-render
155
+ this.progressBar = shadow.querySelector('.progress__bar') as HTMLElement;
156
+ this.circleBar = shadow.querySelector('.progress__circle-bar') as SVGCircleElement;
157
+ this.labelElement = shadow.querySelector('.progress__label') as HTMLElement;
158
+ this.circleLabelElement = shadow.querySelector('.progress__circle-label') as HTMLElement;
159
+
160
+ this.updateProgress();
161
+ }
162
+ }
163
+
164
+ @watch('showLabel', 'label')
165
+ handleLabelChange() {
166
+ this.updateLabel();
167
+ }
168
+
169
+ @watch('thickness')
170
+ handleThicknessChange() {
171
+ if (this.variant === 'circular') {
172
+ this.style.setProperty('--progress-spinner-stroke', `${this.thickness}px`);
173
+ this.handleVariantChange(); // Re-render circular to update stroke
174
+ }
175
+ }
176
+
177
+ private updateProgress() {
178
+ const percentage = this.getPercentage();
179
+
180
+ if (this.variant === 'linear' && this.progressBar) {
181
+ if (!this.indeterminate) {
182
+ this.progressBar.style.width = `${percentage}%`;
183
+ }
184
+
185
+ // Update ARIA attributes
186
+ this.progressBar.parentElement?.setAttribute('aria-valuenow', String(this.value));
187
+ this.progressBar.parentElement?.setAttribute('aria-valuemax', String(this.max));
188
+ } else if (this.variant === 'circular' && this.circleBar) {
189
+ if (!this.indeterminate) {
190
+ const offset = this.circumference - (percentage / 100) * this.circumference;
191
+ this.circleBar.style.strokeDashoffset = String(offset);
192
+ }
193
+
194
+ // Update ARIA attributes
195
+ this.circleBar.parentElement?.parentElement?.setAttribute('aria-valuenow', String(this.value));
196
+ this.circleBar.parentElement?.parentElement?.setAttribute('aria-valuemax', String(this.max));
197
+ }
198
+
199
+ this.updateLabel();
200
+ }
201
+
202
+ private updateLabel() {
203
+ const percentage = this.getPercentage();
204
+ const labelText = this.label || `${Math.round(percentage)}%`;
205
+
206
+ if (this.labelElement) {
207
+ this.labelElement.textContent = labelText;
208
+ }
209
+ if (this.circleLabelElement) {
210
+ this.circleLabelElement.textContent = labelText;
211
+ }
212
+ }
213
+
214
+ getPercentage(): number {
215
+ if (this.indeterminate) return 0;
216
+ if (this.max === 0) return 0;
217
+ return Math.min(100, Math.max(0, (this.value / this.max) * 100));
218
+ }
219
+
220
+ setProgress(value: number, max?: number) {
221
+ this.value = value;
222
+ if (max !== undefined) {
223
+ this.max = max;
224
+ }
225
+ }
226
+
227
+ private getSizeValue(): number {
228
+ switch (this.size) {
229
+ case 'small': return 24;
230
+ case 'large': return 56;
231
+ case 'xl': return 80;
232
+ case 'xxl': return 120;
233
+ case 'xxxl': return 160;
234
+ default: return 40;
235
+ }
236
+ }
237
+
238
+ @dispatch('progress-change', { bubbles: true, composed: true })
239
+ private dispatchProgressChange() {
240
+ return {
241
+ value: this.value,
242
+ max: this.max,
243
+ percentage: this.getPercentage(),
244
+ indeterminate: this.indeterminate
245
+ };
246
+ }
247
+ }
@@ -0,0 +1,19 @@
1
+ export type ProgressVariant = 'linear' | 'circular';
2
+ export type ProgressSize = 'small' | 'medium' | 'large' | 'xl' | 'xxl' | 'xxxl';
3
+ export type ProgressColor = 'primary' | 'success' | 'warning' | 'error' | 'info';
4
+
5
+ export interface SniceProgressElement extends HTMLElement {
6
+ value: number;
7
+ max: number;
8
+ variant: ProgressVariant;
9
+ size: ProgressSize;
10
+ color: ProgressColor;
11
+ indeterminate: boolean;
12
+ showLabel: boolean;
13
+ label: string;
14
+ striped: boolean;
15
+ animated: boolean;
16
+ thickness: number;
17
+ getPercentage(): number;
18
+ setProgress(value: number, max?: number): void;
19
+ }