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,229 @@
1
+ import { element, property, query, on, watch, dispatch, ready } from 'snice';
2
+ import css from './snice-switch.css?inline';
3
+ import type { SwitchSize, SniceSwitchElement } from './snice-switch.types';
4
+
5
+ @element('snice-switch')
6
+ export class SniceSwitch extends HTMLElement implements SniceSwitchElement {
7
+ @property({ type: Boolean, reflect: true })
8
+ checked = false;
9
+
10
+ @property({ type: Boolean, reflect: true })
11
+ disabled = false;
12
+
13
+ @property({ type: Boolean, reflect: true })
14
+ required = false;
15
+
16
+ @property({ type: Boolean, reflect: true })
17
+ invalid = false;
18
+
19
+ @property({ reflect: true })
20
+ size: SwitchSize = 'medium';
21
+
22
+ @property({ reflect: true })
23
+ name = '';
24
+
25
+ @property({ reflect: true })
26
+ value = 'on';
27
+
28
+ @property({ reflect: true })
29
+ label = '';
30
+
31
+ @property({ reflect: true, attribute: 'label-on' })
32
+ labelOn = '';
33
+
34
+ @property({ reflect: true, attribute: 'label-off' })
35
+ labelOff = '';
36
+
37
+ @query('.switch-input')
38
+ input?: HTMLInputElement;
39
+
40
+ @query('.switch-track')
41
+ track?: HTMLElement;
42
+
43
+ @query('.switch-label')
44
+ labelElement?: HTMLElement;
45
+
46
+ @query('.switch-wrapper')
47
+ wrapper?: HTMLElement;
48
+
49
+ @query('.switch-state-label--on')
50
+ onLabel?: HTMLElement;
51
+
52
+ @query('.switch-state-label--off')
53
+ offLabel?: HTMLElement;
54
+
55
+ html() {
56
+ return /*html*/`
57
+ <label class="switch-wrapper ${this.disabled ? 'switch-wrapper--disabled' : ''}">
58
+ <input
59
+ type="checkbox"
60
+ class="switch-input"
61
+ ${this.checked ? 'checked' : ''}
62
+ ${this.disabled ? 'disabled' : ''}
63
+ ${this.required ? 'required' : ''}
64
+ ${this.name ? `name="${this.name}"` : ''}
65
+ ${this.value ? `value="${this.value}"` : ''}
66
+ aria-invalid="${this.invalid}"
67
+ aria-checked="${this.checked}"
68
+ role="switch"
69
+ part="input"
70
+ />
71
+
72
+ <span class="switch-track
73
+ switch-track--${this.size}
74
+ ${this.invalid ? 'switch-track--invalid' : ''}"
75
+ part="track">
76
+ <span class="switch-thumb" part="thumb"></span>
77
+ ${this.labelOn || this.labelOff ? /*html*/`
78
+ <span class="switch-state-label switch-state-label--on">${this.labelOn}</span>
79
+ <span class="switch-state-label switch-state-label--off">${this.labelOff}</span>
80
+ ` : ''}
81
+ </span>
82
+
83
+ ${this.label ? /*html*/`
84
+ <span class="switch-label switch-label--${this.size} ${this.required ? 'switch-label--required' : ''}" part="label">
85
+ ${this.label}
86
+ </span>
87
+ ` : ''}
88
+ </label>
89
+ `;
90
+ }
91
+
92
+ css() {
93
+ return css;
94
+ }
95
+
96
+ @ready()
97
+ init() {
98
+ // Set initial states
99
+ if (this.input) {
100
+ this.input.checked = this.checked;
101
+
102
+ // Set form value
103
+ if (this.name) {
104
+ this.input.name = this.name;
105
+ }
106
+ if (this.value) {
107
+ this.input.value = this.value;
108
+ }
109
+ }
110
+
111
+ // Update state labels if provided
112
+ this.updateStateLabels();
113
+ }
114
+
115
+ @on('change', '.switch-input')
116
+ handleChange(e: Event) {
117
+ const target = e.target as HTMLInputElement;
118
+ this.checked = target.checked;
119
+ this.dispatchChangeEvent();
120
+ }
121
+
122
+ @on('click', '.switch-input')
123
+ handleClick(e: Event) {
124
+ // Allow click to propagate for label association
125
+ e.stopPropagation();
126
+ }
127
+
128
+ @watch('checked')
129
+ handleCheckedChange() {
130
+ if (this.input) {
131
+ this.input.checked = this.checked;
132
+ this.input.setAttribute('aria-checked', String(this.checked));
133
+ }
134
+ }
135
+
136
+ @watch('disabled')
137
+ handleDisabledChange() {
138
+ if (this.input) {
139
+ this.input.disabled = this.disabled;
140
+ }
141
+ if (this.wrapper) {
142
+ this.wrapper.classList.toggle('switch-wrapper--disabled', this.disabled);
143
+ }
144
+ }
145
+
146
+ @watch('invalid')
147
+ handleInvalidChange() {
148
+ if (this.input) {
149
+ this.input.setAttribute('aria-invalid', String(this.invalid));
150
+ }
151
+ if (this.track) {
152
+ this.track.classList.toggle('switch-track--invalid', this.invalid);
153
+ }
154
+ }
155
+
156
+ @watch('required')
157
+ handleRequiredChange() {
158
+ if (this.input) {
159
+ this.input.required = this.required;
160
+ }
161
+ if (this.labelElement) {
162
+ this.labelElement.classList.toggle('switch-label--required', this.required);
163
+ }
164
+ }
165
+
166
+ @watch('label')
167
+ handleLabelChange() {
168
+ if (this.labelElement) {
169
+ this.labelElement.textContent = this.label;
170
+ this.labelElement.style.display = this.label ? '' : 'none';
171
+ }
172
+ }
173
+
174
+ @watch('labelOn', 'labelOff')
175
+ handleStateLabelChange() {
176
+ this.updateStateLabels();
177
+ }
178
+
179
+ @watch('name')
180
+ handleNameChange() {
181
+ if (this.input) {
182
+ this.input.name = this.name;
183
+ }
184
+ }
185
+
186
+ @watch('value')
187
+ handleValueChange() {
188
+ if (this.input) {
189
+ this.input.value = this.value;
190
+ }
191
+ }
192
+
193
+ private updateStateLabels() {
194
+ if (this.onLabel) {
195
+ this.onLabel.textContent = this.labelOn;
196
+ this.onLabel.style.display = this.labelOn ? '' : 'none';
197
+ }
198
+ if (this.offLabel) {
199
+ this.offLabel.textContent = this.labelOff;
200
+ this.offLabel.style.display = this.labelOff ? '' : 'none';
201
+ }
202
+ }
203
+
204
+ @dispatch('@snice/switch-change', { bubbles: true, composed: true })
205
+ private dispatchChangeEvent() {
206
+ return {
207
+ checked: this.checked,
208
+ switch: this
209
+ };
210
+ }
211
+
212
+ // Public API
213
+ focus() {
214
+ this.input?.focus();
215
+ }
216
+
217
+ blur() {
218
+ this.input?.blur();
219
+ }
220
+
221
+ click() {
222
+ this.input?.click();
223
+ }
224
+
225
+ toggle() {
226
+ this.checked = !this.checked;
227
+ this.dispatchChangeEvent();
228
+ }
229
+ }
@@ -0,0 +1,23 @@
1
+ export type SwitchSize = 'small' | 'medium' | 'large';
2
+
3
+ export interface SniceSwitchElement extends HTMLElement {
4
+ checked: boolean;
5
+ disabled: boolean;
6
+ required: boolean;
7
+ invalid: boolean;
8
+ size: SwitchSize;
9
+ name: string;
10
+ value: string;
11
+ label: string;
12
+ labelOn: string;
13
+ labelOff: string;
14
+ focus(): void;
15
+ blur(): void;
16
+ click(): void;
17
+ toggle(): void;
18
+ }
19
+
20
+ export interface SwitchChangeDetail {
21
+ checked: boolean;
22
+ switch: SniceSwitchElement;
23
+ }
@@ -0,0 +1,23 @@
1
+ // Global symbols for all Snice components
2
+ // Ensures components work correctly even if bundled multiple times
3
+
4
+ function getComponentSymbol(namespace: string, name: string): symbol {
5
+ if (!(globalThis as any).sniceComponents) {
6
+ (globalThis as any).sniceComponents = {
7
+ symbols: new Map<string, symbol>()
8
+ };
9
+ }
10
+
11
+ const key = `${namespace}/${name}`;
12
+ const symbols = (globalThis as any).sniceComponents.symbols;
13
+
14
+ if (!symbols.has(key)) {
15
+ symbols.set(key, Symbol(key));
16
+ }
17
+ return symbols.get(key)!;
18
+ }
19
+
20
+ // Export helper for component-specific symbols
21
+ export function getSymbol(namespace: string, name: string): symbol {
22
+ return getComponentSymbol(namespace, name);
23
+ }
@@ -0,0 +1,100 @@
1
+ import { controller, respond, IController } from 'snice';
2
+
3
+ console.log('Loading demo table controller...');
4
+
5
+ @controller('demo-table-controller')
6
+ export class DemoTableController implements IController {
7
+ element: HTMLElement | null = null;
8
+
9
+ async attach(element: HTMLElement) {
10
+ this.element = element;
11
+ console.log('Demo table controller attached');
12
+ }
13
+
14
+ async detach(_element: HTMLElement) {
15
+ console.log('Demo table controller detached');
16
+ }
17
+
18
+ private sampleData = [
19
+ { id: 1, name: 'John Doe', email: 'john.doe@example.com', role: 'Developer', salary: 75000, joinDate: '2023-01-15', active: true },
20
+ { id: 2, name: 'Jane Smith', email: 'jane.smith@example.com', role: 'Designer', salary: 68000, joinDate: '2023-03-20', active: true },
21
+ { id: 3, name: 'Bob Johnson', email: 'bob.johnson@example.com', role: 'Manager', salary: 95000, joinDate: '2022-11-10', active: false },
22
+ { id: 4, name: 'Alice Brown', email: 'alice.brown@example.com', role: 'Developer', salary: 72000, joinDate: '2023-06-05', active: true },
23
+ { id: 5, name: 'Charlie Wilson', email: 'charlie.wilson@example.com', role: 'QA Engineer', salary: 65000, joinDate: '2023-02-28', active: true },
24
+ { id: 6, name: 'David Lee', email: 'david.lee@example.com', role: 'Developer', salary: 78000, joinDate: '2023-04-12', active: true },
25
+ { id: 7, name: 'Emily Davis', email: 'emily.davis@example.com', role: 'Designer', salary: 70000, joinDate: '2023-05-18', active: false },
26
+ { id: 8, name: 'Frank Miller', email: 'frank.miller@example.com', role: 'Manager', salary: 98000, joinDate: '2022-08-22', active: true }
27
+ ];
28
+
29
+ @respond('@snice/table/config')
30
+ async getTableConfig() {
31
+ // Return table configuration
32
+ return {
33
+ columns: [
34
+ { key: 'id', label: 'ID', type: 'number', align: 'right' },
35
+ { key: 'name', label: 'Full Name', type: 'text' },
36
+ { key: 'email', label: 'Email', type: 'text' },
37
+ { key: 'role', label: 'Role', type: 'text', align: 'center' },
38
+ { key: 'salary', label: 'Salary', type: 'currency', prefix: '$', thousandsSeparator: true, decimals: 0 },
39
+ { key: 'joinDate', label: 'Join Date', type: 'date', dateFormat: 'short' },
40
+ { key: 'active', label: 'Status', type: 'boolean', useSymbols: true, trueSymbol: '✅', falseSymbol: '❌' }
41
+ ],
42
+ selectorOptions: [
43
+ { value: 'Developer', label: 'Developer' },
44
+ { value: 'Designer', label: 'Designer' },
45
+ { value: 'Manager', label: 'Manager' },
46
+ { value: 'QA Engineer', label: 'QA Engineer' }
47
+ ]
48
+ };
49
+ }
50
+
51
+ @respond('@snice/table/data')
52
+ async getTableData(params: any) {
53
+ // Add fake delay to see loading skeleton
54
+ await new Promise(resolve => setTimeout(resolve, 1500));
55
+
56
+ let filteredData = [...this.sampleData];
57
+
58
+ // Apply search filter
59
+ if (params.search) {
60
+ const searchLower = params.search.toLowerCase();
61
+ filteredData = filteredData.filter(row =>
62
+ Object.values(row).some(val =>
63
+ String(val).toLowerCase().includes(searchLower)
64
+ )
65
+ );
66
+ }
67
+
68
+ // Apply selector filter
69
+ if (params.selector) {
70
+ const selectedRoles = params.selector.split(',');
71
+ filteredData = filteredData.filter(row =>
72
+ selectedRoles.includes(row.role)
73
+ );
74
+ }
75
+
76
+ // Apply sorting
77
+ if (params.sort && params.sort.length > 0) {
78
+ filteredData.sort((a: any, b: any) => {
79
+ for (const sortItem of params.sort) {
80
+ const aVal = a[sortItem.column];
81
+ const bVal = b[sortItem.column];
82
+
83
+ let comparison = 0;
84
+ if (aVal < bVal) comparison = -1;
85
+ else if (aVal > bVal) comparison = 1;
86
+
87
+ if (comparison !== 0) {
88
+ return sortItem.direction === 'desc' ? -comparison : comparison;
89
+ }
90
+ }
91
+ return 0;
92
+ });
93
+ }
94
+
95
+ return {
96
+ data: filteredData,
97
+ total: filteredData.length
98
+ };
99
+ }
100
+ }