snice 2.5.4 → 3.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.
- package/README.md +501 -882
- package/bin/templates/base/src/components/counter-button.ts +13 -26
- package/bin/templates/base/src/controllers/counter-controller.ts +3 -3
- package/dist/components/accordion/snice-accordion-item.d.ts +4 -5
- package/dist/components/accordion/snice-accordion-item.js +37 -39
- package/dist/components/accordion/snice-accordion-item.js.map +1 -1
- package/dist/components/accordion/snice-accordion.d.ts +5 -11
- package/dist/components/accordion/snice-accordion.js +51 -52
- package/dist/components/accordion/snice-accordion.js.map +1 -1
- package/dist/components/alert/snice-alert.d.ts +2 -6
- package/dist/components/alert/snice-alert.js +41 -56
- package/dist/components/alert/snice-alert.js.map +1 -1
- package/dist/components/avatar/snice-avatar.d.ts +2 -6
- package/dist/components/avatar/snice-avatar.js +64 -71
- package/dist/components/avatar/snice-avatar.js.map +1 -1
- package/dist/components/badge/snice-badge.d.ts +2 -3
- package/dist/components/badge/snice-badge.js +22 -23
- package/dist/components/badge/snice-badge.js.map +1 -1
- package/dist/components/breadcrumbs/snice-breadcrumbs.d.ts +5 -12
- package/dist/components/breadcrumbs/snice-breadcrumbs.js +88 -89
- package/dist/components/breadcrumbs/snice-breadcrumbs.js.map +1 -1
- package/dist/components/button/snice-button.d.ts +3 -7
- package/dist/components/button/snice-button.js +37 -58
- package/dist/components/button/snice-button.js.map +1 -1
- package/dist/components/card/snice-card.d.ts +5 -8
- package/dist/components/card/snice-card.js +71 -56
- package/dist/components/card/snice-card.js.map +1 -1
- package/dist/components/checkbox/snice-checkbox.d.ts +4 -13
- package/dist/components/checkbox/snice-checkbox.js +66 -137
- package/dist/components/checkbox/snice-checkbox.js.map +1 -1
- package/dist/components/chip/snice-chip.d.ts +5 -11
- package/dist/components/chip/snice-chip.js +44 -47
- package/dist/components/chip/snice-chip.js.map +1 -1
- package/dist/components/date-picker/snice-date-picker.d.ts +11 -11
- package/dist/components/date-picker/snice-date-picker.js +134 -133
- package/dist/components/date-picker/snice-date-picker.js.map +1 -1
- package/dist/components/divider/snice-divider.d.ts +2 -4
- package/dist/components/divider/snice-divider.js +14 -22
- package/dist/components/divider/snice-divider.js.map +1 -1
- package/dist/components/drawer/snice-drawer.d.ts +4 -4
- package/dist/components/drawer/snice-drawer.js +25 -19
- package/dist/components/drawer/snice-drawer.js.map +1 -1
- package/dist/components/input/snice-input.d.ts +8 -6
- package/dist/components/input/snice-input.js +122 -105
- package/dist/components/input/snice-input.js.map +1 -1
- package/dist/components/layout/snice-layout-blog.d.ts +4 -4
- package/dist/components/layout/snice-layout-blog.js +21 -19
- package/dist/components/layout/snice-layout-blog.js.map +1 -1
- package/dist/components/layout/snice-layout-card.d.ts +2 -2
- package/dist/components/layout/snice-layout-card.js +16 -9
- package/dist/components/layout/snice-layout-card.js.map +1 -1
- package/dist/components/layout/snice-layout-centered.d.ts +2 -2
- package/dist/components/layout/snice-layout-centered.js +14 -7
- package/dist/components/layout/snice-layout-centered.js.map +1 -1
- package/dist/components/layout/snice-layout-dashboard.d.ts +5 -5
- package/dist/components/layout/snice-layout-dashboard.js +38 -30
- package/dist/components/layout/snice-layout-dashboard.js.map +1 -1
- package/dist/components/layout/snice-layout-fullscreen.d.ts +2 -2
- package/dist/components/layout/snice-layout-fullscreen.js +17 -10
- package/dist/components/layout/snice-layout-fullscreen.js.map +1 -1
- package/dist/components/layout/snice-layout-landing.d.ts +4 -4
- package/dist/components/layout/snice-layout-landing.js +21 -19
- package/dist/components/layout/snice-layout-landing.js.map +1 -1
- package/dist/components/layout/snice-layout-minimal.d.ts +2 -2
- package/dist/components/layout/snice-layout-minimal.js +17 -6
- package/dist/components/layout/snice-layout-minimal.js.map +1 -1
- package/dist/components/layout/snice-layout-sidebar.d.ts +5 -4
- package/dist/components/layout/snice-layout-sidebar.js +42 -20
- package/dist/components/layout/snice-layout-sidebar.js.map +1 -1
- package/dist/components/layout/snice-layout-split.d.ts +2 -2
- package/dist/components/layout/snice-layout-split.js +14 -7
- package/dist/components/layout/snice-layout-split.js.map +1 -1
- package/dist/components/layout/snice-layout.d.ts +4 -4
- package/dist/components/layout/snice-layout.js +16 -10
- package/dist/components/layout/snice-layout.js.map +1 -1
- package/dist/components/login/snice-login.d.ts +6 -11
- package/dist/components/login/snice-login.js +97 -71
- package/dist/components/login/snice-login.js.map +1 -1
- package/dist/components/modal/snice-modal.d.ts +5 -9
- package/dist/components/modal/snice-modal.js +47 -78
- package/dist/components/modal/snice-modal.js.map +1 -1
- package/dist/components/nav/snice-nav.d.ts +13 -7
- package/dist/components/nav/snice-nav.js +191 -100
- package/dist/components/nav/snice-nav.js.map +1 -1
- package/dist/components/nav/snice-nav.types.d.ts +3 -3
- package/dist/components/pagination/snice-pagination.d.ts +6 -7
- package/dist/components/pagination/snice-pagination.js +94 -81
- package/dist/components/pagination/snice-pagination.js.map +1 -1
- package/dist/components/progress/snice-progress.d.ts +2 -7
- package/dist/components/progress/snice-progress.js +41 -98
- package/dist/components/progress/snice-progress.js.map +1 -1
- package/dist/components/radio/snice-radio.d.ts +4 -4
- package/dist/components/radio/snice-radio.js +52 -44
- package/dist/components/radio/snice-radio.js.map +1 -1
- package/dist/components/select/snice-option.d.ts +2 -1
- package/dist/components/select/snice-option.js +12 -5
- package/dist/components/select/snice-option.js.map +1 -1
- package/dist/components/select/snice-select.d.ts +9 -21
- package/dist/components/select/snice-select.js +98 -170
- package/dist/components/select/snice-select.js.map +1 -1
- package/dist/components/skeleton/snice-skeleton.d.ts +2 -6
- package/dist/components/skeleton/snice-skeleton.js +18 -49
- package/dist/components/skeleton/snice-skeleton.js.map +1 -1
- package/dist/components/snice-cell-BLFVdxPp.js +4 -0
- package/dist/components/snice-cell-BLFVdxPp.js.map +1 -0
- package/dist/components/switch/snice-switch.d.ts +2 -2
- package/dist/components/switch/snice-switch.js +38 -26
- package/dist/components/switch/snice-switch.js.map +1 -1
- package/dist/components/table/snice-cell-actions.d.ts +24 -0
- package/dist/components/table/snice-cell-actions.js +149 -0
- package/dist/components/table/snice-cell-actions.js.map +1 -0
- package/dist/components/table/snice-cell-boolean.d.ts +2 -2
- package/dist/components/table/snice-cell-boolean.js +13 -7
- package/dist/components/table/snice-cell-boolean.js.map +1 -1
- package/dist/components/table/snice-cell-color.d.ts +18 -0
- package/dist/components/table/snice-cell-color.js +149 -0
- package/dist/components/table/snice-cell-color.js.map +1 -0
- package/dist/components/table/snice-cell-currency.d.ts +24 -0
- package/dist/components/table/snice-cell-currency.js +235 -0
- package/dist/components/table/snice-cell-currency.js.map +1 -0
- package/dist/components/table/snice-cell-date.d.ts +2 -2
- package/dist/components/table/snice-cell-date.js +14 -8
- package/dist/components/table/snice-cell-date.js.map +1 -1
- package/dist/components/table/snice-cell-duration.d.ts +2 -2
- package/dist/components/table/snice-cell-duration.js +12 -6
- package/dist/components/table/snice-cell-duration.js.map +1 -1
- package/dist/components/table/snice-cell-email.d.ts +15 -0
- package/dist/components/table/snice-cell-email.js +125 -0
- package/dist/components/table/snice-cell-email.js.map +1 -0
- package/dist/components/table/snice-cell-filesize.d.ts +2 -2
- package/dist/components/table/snice-cell-filesize.js +12 -6
- package/dist/components/table/snice-cell-filesize.js.map +1 -1
- package/dist/components/table/snice-cell-image.d.ts +20 -0
- package/dist/components/table/snice-cell-image.js +162 -0
- package/dist/components/table/snice-cell-image.js.map +1 -0
- package/dist/components/table/snice-cell-json.d.ts +20 -0
- package/dist/components/table/snice-cell-json.js +186 -0
- package/dist/components/table/snice-cell-json.js.map +1 -0
- package/dist/components/table/snice-cell-link.d.ts +17 -0
- package/dist/components/table/snice-cell-link.js +142 -0
- package/dist/components/table/snice-cell-link.js.map +1 -0
- package/dist/components/table/snice-cell-location.d.ts +19 -0
- package/dist/components/table/snice-cell-location.js +185 -0
- package/dist/components/table/snice-cell-location.js.map +1 -0
- package/dist/components/table/snice-cell-number.d.ts +2 -2
- package/dist/components/table/snice-cell-number.js +12 -6
- package/dist/components/table/snice-cell-number.js.map +1 -1
- package/dist/components/table/snice-cell-percentage.d.ts +22 -0
- package/dist/components/table/snice-cell-percentage.js +208 -0
- package/dist/components/table/snice-cell-percentage.js.map +1 -0
- package/dist/components/table/snice-cell-phone.d.ts +18 -0
- package/dist/components/table/snice-cell-phone.js +153 -0
- package/dist/components/table/snice-cell-phone.js.map +1 -0
- package/dist/components/table/snice-cell-progress.d.ts +2 -2
- package/dist/components/table/snice-cell-progress.js +12 -6
- package/dist/components/table/snice-cell-progress.js.map +1 -1
- package/dist/components/table/snice-cell-rating.d.ts +2 -2
- package/dist/components/table/snice-cell-rating.js +12 -6
- package/dist/components/table/snice-cell-rating.js.map +1 -1
- package/dist/components/table/snice-cell-sparkline.d.ts +2 -2
- package/dist/components/table/snice-cell-sparkline.js +13 -7
- package/dist/components/table/snice-cell-sparkline.js.map +1 -1
- package/dist/components/table/snice-cell-status.d.ts +17 -0
- package/dist/components/table/snice-cell-status.js +144 -0
- package/dist/components/table/snice-cell-status.js.map +1 -0
- package/dist/components/table/snice-cell-tag.d.ts +16 -0
- package/dist/components/table/snice-cell-tag.js +131 -0
- package/dist/components/table/snice-cell-tag.js.map +1 -0
- package/dist/components/table/snice-cell-text.d.ts +2 -2
- package/dist/components/table/snice-cell-text.js +14 -8
- package/dist/components/table/snice-cell-text.js.map +1 -1
- package/dist/components/table/snice-cell.d.ts +2 -2
- package/dist/components/table/snice-cell.js +12 -6
- package/dist/components/table/snice-cell.js.map +1 -1
- package/dist/components/table/snice-column.d.ts +1 -1
- package/dist/components/table/snice-column.js +6 -3
- package/dist/components/table/snice-column.js.map +1 -1
- package/dist/components/table/snice-header.d.ts +5 -5
- package/dist/components/table/snice-header.js +60 -50
- package/dist/components/table/snice-header.js.map +1 -1
- package/dist/components/table/snice-progress.d.ts +2 -2
- package/dist/components/table/snice-progress.js +18 -11
- package/dist/components/table/snice-progress.js.map +1 -1
- package/dist/components/table/snice-rating.d.ts +2 -2
- package/dist/components/table/snice-rating.js +15 -8
- package/dist/components/table/snice-rating.js.map +1 -1
- package/dist/components/table/snice-row.d.ts +17 -6
- package/dist/components/table/snice-row.js +95 -44
- package/dist/components/table/snice-row.js.map +1 -1
- package/dist/components/table/snice-table.d.ts +18 -10
- package/dist/components/table/snice-table.js +355 -173
- package/dist/components/table/snice-table.js.map +1 -1
- package/dist/components/table/snice-table.types.d.ts +101 -2
- package/dist/components/tabs/snice-tab-panel.d.ts +2 -2
- package/dist/components/tabs/snice-tab-panel.js +12 -6
- package/dist/components/tabs/snice-tab-panel.js.map +1 -1
- package/dist/components/tabs/snice-tab.d.ts +6 -5
- package/dist/components/tabs/snice-tab.js +36 -19
- package/dist/components/tabs/snice-tab.js.map +1 -1
- package/dist/components/tabs/snice-tabs.d.ts +5 -5
- package/dist/components/tabs/snice-tabs.js +38 -28
- package/dist/components/tabs/snice-tabs.js.map +1 -1
- package/dist/components/toast/snice-toast-container.d.ts +7 -7
- package/dist/components/toast/snice-toast-container.js +19 -12
- package/dist/components/toast/snice-toast-container.js.map +1 -1
- package/dist/components/toast/snice-toast.d.ts +3 -15
- package/dist/components/toast/snice-toast.js +49 -108
- package/dist/components/toast/snice-toast.js.map +1 -1
- package/dist/components/tooltip/snice-tooltip.d.ts +2 -2
- package/dist/components/tooltip/snice-tooltip.js +14 -7
- package/dist/components/tooltip/snice-tooltip.js.map +1 -1
- package/dist/context.d.ts +44 -0
- package/dist/element-ready.d.ts +40 -0
- package/dist/{types/element.d.ts → element.d.ts} +2 -8
- package/dist/{types/events.d.ts → events.d.ts} +0 -4
- package/dist/index.cjs +2589 -605
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.ts +21 -0
- package/dist/index.esm.js +2568 -604
- package/dist/index.esm.js.map +1 -1
- package/dist/index.iife.js +2589 -605
- package/dist/index.iife.js.map +1 -1
- package/dist/method-decorators.d.ts +121 -0
- package/dist/on.d.ts +59 -0
- package/dist/parts.d.ts +159 -0
- package/dist/render-debug.d.ts +27 -0
- package/dist/render-tracker.d.ts +14 -0
- package/dist/render.d.ts +96 -0
- package/dist/symbols.cjs +163 -0
- package/dist/symbols.cjs.map +1 -1
- package/dist/{types/symbols.d.ts → symbols.d.ts} +22 -0
- package/dist/symbols.esm.js +27 -3
- package/dist/symbols.esm.js.map +1 -1
- package/dist/template.d.ts +100 -0
- package/dist/transitions.cjs +219 -0
- package/dist/transitions.esm.js +2 -2
- package/dist/types/context.d.ts +48 -0
- package/dist/types/element-options.d.ts +26 -0
- package/dist/types/index.d.ts +25 -9
- package/dist/types/nav-context.d.ts +19 -0
- package/dist/types/{types/on-options.d.ts → on-options.d.ts} +2 -0
- package/dist/types/{types/placard.d.ts → placard.d.ts} +0 -1
- package/docs/ai/README.md +17 -0
- package/docs/ai/api.md +175 -0
- package/docs/ai/architecture.md +160 -0
- package/docs/ai/components/accordion.md +174 -0
- package/docs/ai/components/alert.md +77 -0
- package/docs/ai/components/avatar.md +61 -0
- package/docs/ai/components/badge.md +69 -0
- package/docs/ai/components/breadcrumbs.md +74 -0
- package/docs/ai/components/button.md +75 -0
- package/docs/ai/components/card.md +61 -0
- package/docs/ai/components/checkbox.md +74 -0
- package/docs/ai/components/chip.md +73 -0
- package/docs/ai/components/date-picker.md +75 -0
- package/docs/ai/components/divider.md +66 -0
- package/docs/ai/components/drawer.md +80 -0
- package/docs/ai/components/input.md +111 -0
- package/docs/ai/components/login.md +109 -0
- package/docs/ai/components/modal.md +67 -0
- package/docs/ai/components/nav.md +76 -0
- package/docs/ai/components/pagination.md +55 -0
- package/docs/ai/components/progress.md +72 -0
- package/docs/ai/components/radio.md +79 -0
- package/docs/ai/components/select.md +92 -0
- package/docs/ai/components/skeleton.md +57 -0
- package/docs/ai/components/switch.md +53 -0
- package/docs/ai/components/table.md +227 -0
- package/docs/ai/components/tabs.md +83 -0
- package/docs/ai/components/toast.md +140 -0
- package/docs/ai/components/tooltip.md +146 -0
- package/docs/ai/patterns.md +244 -0
- package/docs/components/accordion.md +558 -0
- package/docs/components/drawer.md +602 -0
- package/docs/components/modal.md +558 -0
- package/docs/components/nav.md +239 -0
- package/docs/components/pagination.md +289 -0
- package/docs/components/select.md +599 -0
- package/docs/components/switch.md +354 -0
- package/docs/components/tabs.md +546 -0
- package/docs/components/toast.md +506 -0
- package/docs/components/tooltip.md +523 -0
- package/docs/controllers.md +744 -0
- package/docs/elements.md +855 -0
- package/docs/events.md +807 -0
- package/docs/migration-v2-to-v3.md +569 -0
- package/docs/observe.md +588 -0
- package/docs/placards.md +401 -0
- package/docs/request-response.md +852 -0
- package/docs/routing.md +1186 -0
- package/package.json +10 -11
- package/dist/components/snice-cell-C9N6yGxQ.js +0 -4
- package/dist/components/snice-cell-C9N6yGxQ.js.map +0 -1
- package/dist/types/types/index.d.ts +0 -23
- /package/dist/{types/controller.d.ts → controller.d.ts} +0 -0
- /package/dist/{types/global.d.ts → global.d.ts} +0 -0
- /package/dist/{types/observe.d.ts → observe.d.ts} +0 -0
- /package/dist/{types/request-response.d.ts → request-response.d.ts} +0 -0
- /package/dist/{types/router.d.ts → router.d.ts} +0 -0
- /package/dist/{types/testing.d.ts → testing.d.ts} +0 -0
- /package/dist/{types/transitions.d.ts → transitions.d.ts} +0 -0
- /package/dist/types/{types/adopted-options.d.ts → adopted-options.d.ts} +0 -0
- /package/dist/types/{types/app-context.d.ts → app-context.d.ts} +0 -0
- /package/dist/types/{types/dispatch-options.d.ts → dispatch-options.d.ts} +0 -0
- /package/dist/types/{types/guard.d.ts → guard.d.ts} +0 -0
- /package/dist/types/{types/i-controller.d.ts → i-controller.d.ts} +0 -0
- /package/dist/types/{types/moved-options.d.ts → moved-options.d.ts} +0 -0
- /package/dist/types/{types/observe-options.d.ts → observe-options.d.ts} +0 -0
- /package/dist/types/{types/page-options.d.ts → page-options.d.ts} +0 -0
- /package/dist/types/{types/part-options.d.ts → part-options.d.ts} +0 -0
- /package/dist/types/{types/property-converter.d.ts → property-converter.d.ts} +0 -0
- /package/dist/types/{types/property-options.d.ts → property-options.d.ts} +0 -0
- /package/dist/types/{types/query-options.d.ts → query-options.d.ts} +0 -0
- /package/dist/types/{types/request-options.d.ts → request-options.d.ts} +0 -0
- /package/dist/types/{types/respond-options.d.ts → respond-options.d.ts} +0 -0
- /package/dist/types/{types/route-params.d.ts → route-params.d.ts} +0 -0
- /package/dist/types/{types/router-instance.d.ts → router-instance.d.ts} +0 -0
- /package/dist/types/{types/router-options.d.ts → router-options.d.ts} +0 -0
- /package/dist/types/{types/simple-array.d.ts → simple-array.d.ts} +0 -0
- /package/dist/types/{types/snice-element.d.ts → snice-element.d.ts} +0 -0
- /package/dist/types/{types/snice-global.d.ts → snice-global.d.ts} +0 -0
- /package/dist/types/{types/transition.d.ts → transition.d.ts} +0 -0
- /package/dist/{types/utils.d.ts → utils.d.ts} +0 -0
|
@@ -0,0 +1,569 @@
|
|
|
1
|
+
# Migration Guide: Snice v2.x → v3.0.0
|
|
2
|
+
|
|
3
|
+
## Breaking Changes Summary
|
|
4
|
+
|
|
5
|
+
Snice v3.0.0 introduces a complete rewrite of the rendering system with **differential rendering** and **tagged templates**, inspired by lit-html but with a custom implementation. This is a **major breaking change** with no backward compatibility.
|
|
6
|
+
|
|
7
|
+
### Removed APIs
|
|
8
|
+
- ❌ `html()` method
|
|
9
|
+
- ❌ `css()` method
|
|
10
|
+
- ❌ `@part` decorator
|
|
11
|
+
|
|
12
|
+
### Event Handling with @on
|
|
13
|
+
- ✅ `@on` decorator available
|
|
14
|
+
- Works in both elements AND controllers
|
|
15
|
+
- Supports event delegation with selectors
|
|
16
|
+
- Supports keyboard modifiers (`@on('keydown:Enter')`)
|
|
17
|
+
- Supports debounce and throttle options
|
|
18
|
+
|
|
19
|
+
### New APIs
|
|
20
|
+
- ✅ `html``template literals
|
|
21
|
+
- ✅ `css``template literals
|
|
22
|
+
- ✅ `@render()` decorator
|
|
23
|
+
- ✅ `@styles()` decorator
|
|
24
|
+
- ✅ Template event syntax (`@click`, `@input`, `@keydown:Enter`)
|
|
25
|
+
- Now supports keyboard modifiers with both `.` and `:` notation
|
|
26
|
+
- ✅ Template property binding (`.value`)
|
|
27
|
+
- ✅ Template boolean attributes (`?disabled`)
|
|
28
|
+
- ✅ Auto-rendering on property changes
|
|
29
|
+
- ✅ Differential rendering (only updates changed parts)
|
|
30
|
+
|
|
31
|
+
---
|
|
32
|
+
|
|
33
|
+
## Migration Steps
|
|
34
|
+
|
|
35
|
+
### Step 1: Update Rendering Methods
|
|
36
|
+
|
|
37
|
+
**Before (v2.x):**
|
|
38
|
+
```typescript
|
|
39
|
+
@element('my-counter')
|
|
40
|
+
class Counter extends HTMLElement {
|
|
41
|
+
@property({ type: Number })
|
|
42
|
+
count = 0;
|
|
43
|
+
|
|
44
|
+
html() {
|
|
45
|
+
return `
|
|
46
|
+
<div class="counter">
|
|
47
|
+
<span>${this.count}</span>
|
|
48
|
+
<button>Increment</button>
|
|
49
|
+
</div>
|
|
50
|
+
`;
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
css() {
|
|
54
|
+
return `
|
|
55
|
+
.counter {
|
|
56
|
+
padding: 1rem;
|
|
57
|
+
background: #f0f0f0;
|
|
58
|
+
}
|
|
59
|
+
`;
|
|
60
|
+
}
|
|
61
|
+
}
|
|
62
|
+
```
|
|
63
|
+
|
|
64
|
+
**After (v3.0.0):**
|
|
65
|
+
```typescript
|
|
66
|
+
import { element, property, render, styles, html, css } from 'snice';
|
|
67
|
+
|
|
68
|
+
@element('my-counter')
|
|
69
|
+
class Counter extends HTMLElement {
|
|
70
|
+
@property({ type: Number })
|
|
71
|
+
count = 0;
|
|
72
|
+
|
|
73
|
+
@render()
|
|
74
|
+
renderContent() {
|
|
75
|
+
return html`
|
|
76
|
+
<div class="counter">
|
|
77
|
+
<span>${this.count}</span>
|
|
78
|
+
<button>Increment</button>
|
|
79
|
+
</div>
|
|
80
|
+
`;
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
@styles()
|
|
84
|
+
componentStyles() {
|
|
85
|
+
return css`
|
|
86
|
+
.counter {
|
|
87
|
+
padding: 1rem;
|
|
88
|
+
background: #f0f0f0;
|
|
89
|
+
}
|
|
90
|
+
`;
|
|
91
|
+
}
|
|
92
|
+
}
|
|
93
|
+
```
|
|
94
|
+
|
|
95
|
+
**Key Changes:**
|
|
96
|
+
- Import `html` and `css` tagged template functions
|
|
97
|
+
- Import `@render` and `@styles` decorators
|
|
98
|
+
- Replace `html()` with `@render()` method returning `html\`...\``
|
|
99
|
+
- Replace `css()` with `@styles()` method returning `css\`...\``
|
|
100
|
+
|
|
101
|
+
---
|
|
102
|
+
|
|
103
|
+
### Step 2: Event Handlers - Two Options!
|
|
104
|
+
|
|
105
|
+
**v3.0.0 gives you TWO ways to handle events:**
|
|
106
|
+
|
|
107
|
+
#### Option A: Template Event Syntax (Recommended for simple cases)
|
|
108
|
+
|
|
109
|
+
**Before (v2.x):**
|
|
110
|
+
```typescript
|
|
111
|
+
@element('my-button')
|
|
112
|
+
class MyButton extends HTMLElement {
|
|
113
|
+
html() {
|
|
114
|
+
return `<button>Click me</button>`;
|
|
115
|
+
}
|
|
116
|
+
|
|
117
|
+
@on('click', 'button')
|
|
118
|
+
handleClick(event: Event) {
|
|
119
|
+
console.log('Clicked!', event);
|
|
120
|
+
}
|
|
121
|
+
}
|
|
122
|
+
```
|
|
123
|
+
|
|
124
|
+
**After (v3.0.0):**
|
|
125
|
+
```typescript
|
|
126
|
+
import { element, render, html } from 'snice';
|
|
127
|
+
|
|
128
|
+
@element('my-button')
|
|
129
|
+
class MyButton extends HTMLElement {
|
|
130
|
+
@render()
|
|
131
|
+
renderContent() {
|
|
132
|
+
return html`
|
|
133
|
+
<button @click=${this.handleClick}>Click me</button>
|
|
134
|
+
<input @keydown:Enter=${this.handleEnter} />
|
|
135
|
+
`;
|
|
136
|
+
}
|
|
137
|
+
|
|
138
|
+
handleClick(event: Event) {
|
|
139
|
+
console.log('Clicked!', event);
|
|
140
|
+
}
|
|
141
|
+
|
|
142
|
+
handleEnter(event: KeyboardEvent) {
|
|
143
|
+
console.log('Enter pressed!');
|
|
144
|
+
}
|
|
145
|
+
}
|
|
146
|
+
```
|
|
147
|
+
|
|
148
|
+
#### Option B: `@on` Decorator
|
|
149
|
+
|
|
150
|
+
**The `@on` decorator works in both elements and controllers!**
|
|
151
|
+
|
|
152
|
+
```typescript
|
|
153
|
+
import { element, render, html, on } from 'snice';
|
|
154
|
+
|
|
155
|
+
@element('my-button')
|
|
156
|
+
class MyButton extends HTMLElement {
|
|
157
|
+
@render()
|
|
158
|
+
renderContent() {
|
|
159
|
+
return html`
|
|
160
|
+
<button>Click me</button>
|
|
161
|
+
<input type="text" placeholder="Press Enter..." />
|
|
162
|
+
`;
|
|
163
|
+
}
|
|
164
|
+
|
|
165
|
+
// Event delegation with selectors
|
|
166
|
+
@on('click', 'button')
|
|
167
|
+
handleClick(event: Event) {
|
|
168
|
+
console.log('Button clicked!', event);
|
|
169
|
+
}
|
|
170
|
+
|
|
171
|
+
// Keyboard modifiers
|
|
172
|
+
@on('keydown:Enter', 'input')
|
|
173
|
+
handleEnter(event: KeyboardEvent) {
|
|
174
|
+
console.log('Enter pressed in input!');
|
|
175
|
+
}
|
|
176
|
+
|
|
177
|
+
// Debounce support
|
|
178
|
+
@on('input', 'input', { debounce: 300 })
|
|
179
|
+
handleInput(event: Event) {
|
|
180
|
+
console.log('Input value:', (event.target as HTMLInputElement).value);
|
|
181
|
+
}
|
|
182
|
+
}
|
|
183
|
+
```
|
|
184
|
+
|
|
185
|
+
**Key Features:**
|
|
186
|
+
- ✅ Event delegation with CSS selectors
|
|
187
|
+
- ✅ Keyboard modifiers (`keydown:Enter`, `keydown:ctrl+s`)
|
|
188
|
+
- ✅ Debounce and throttle options
|
|
189
|
+
- ✅ preventDefault and stopPropagation options
|
|
190
|
+
- ✅ Works in both elements AND controllers
|
|
191
|
+
|
|
192
|
+
---
|
|
193
|
+
|
|
194
|
+
### Step 3: Automatic Re-rendering
|
|
195
|
+
|
|
196
|
+
**Before (v2.x):**
|
|
197
|
+
```typescript
|
|
198
|
+
@element('user-profile')
|
|
199
|
+
class UserProfile extends HTMLElement {
|
|
200
|
+
@property()
|
|
201
|
+
name = '';
|
|
202
|
+
|
|
203
|
+
html() {
|
|
204
|
+
return `<h1>${this.name}</h1>`;
|
|
205
|
+
}
|
|
206
|
+
|
|
207
|
+
@on('click', 'button')
|
|
208
|
+
updateName() {
|
|
209
|
+
this.name = 'New Name';
|
|
210
|
+
// Manual re-render required!
|
|
211
|
+
this.shadowRoot!.innerHTML = this.html();
|
|
212
|
+
}
|
|
213
|
+
}
|
|
214
|
+
```
|
|
215
|
+
|
|
216
|
+
**After (v3.0.0):**
|
|
217
|
+
```typescript
|
|
218
|
+
import { element, property, render, html } from 'snice';
|
|
219
|
+
|
|
220
|
+
@element('user-profile')
|
|
221
|
+
class UserProfile extends HTMLElement {
|
|
222
|
+
@property()
|
|
223
|
+
name = '';
|
|
224
|
+
|
|
225
|
+
@render()
|
|
226
|
+
renderContent() {
|
|
227
|
+
return html`
|
|
228
|
+
<h1>${this.name}</h1>
|
|
229
|
+
<button @click=${this.updateName}>Update</button>
|
|
230
|
+
`;
|
|
231
|
+
}
|
|
232
|
+
|
|
233
|
+
updateName() {
|
|
234
|
+
this.name = 'New Name';
|
|
235
|
+
// Auto re-renders! No manual render needed!
|
|
236
|
+
}
|
|
237
|
+
}
|
|
238
|
+
```
|
|
239
|
+
|
|
240
|
+
**Key Changes:**
|
|
241
|
+
- **Automatic re-rendering** when properties change
|
|
242
|
+
- **Differential rendering** - only updates changed parts
|
|
243
|
+
- **No manual `innerHTML` manipulation** needed
|
|
244
|
+
|
|
245
|
+
---
|
|
246
|
+
|
|
247
|
+
### Step 4: Replace @part with Differential Rendering
|
|
248
|
+
|
|
249
|
+
**Before (v2.x):**
|
|
250
|
+
```typescript
|
|
251
|
+
@element('todo-list')
|
|
252
|
+
class TodoList extends HTMLElement {
|
|
253
|
+
todos = ['Task 1', 'Task 2'];
|
|
254
|
+
|
|
255
|
+
html() {
|
|
256
|
+
return `
|
|
257
|
+
<div>
|
|
258
|
+
<ul part="todos"></ul>
|
|
259
|
+
<button>Add</button>
|
|
260
|
+
</div>
|
|
261
|
+
`;
|
|
262
|
+
}
|
|
263
|
+
|
|
264
|
+
@part('todos')
|
|
265
|
+
renderTodos() {
|
|
266
|
+
return this.todos.map(t => `<li>${t}</li>`).join('');
|
|
267
|
+
}
|
|
268
|
+
|
|
269
|
+
@on('click', 'button')
|
|
270
|
+
addTodo() {
|
|
271
|
+
this.todos.push('New Task');
|
|
272
|
+
this.renderTodos(); // Manual partial update
|
|
273
|
+
}
|
|
274
|
+
}
|
|
275
|
+
```
|
|
276
|
+
|
|
277
|
+
**After (v3.0.0):**
|
|
278
|
+
```typescript
|
|
279
|
+
import { element, render, html } from 'snice';
|
|
280
|
+
|
|
281
|
+
@element('todo-list')
|
|
282
|
+
class TodoList extends HTMLElement {
|
|
283
|
+
todos = ['Task 1', 'Task 2'];
|
|
284
|
+
|
|
285
|
+
@render()
|
|
286
|
+
renderContent() {
|
|
287
|
+
return html`
|
|
288
|
+
<div>
|
|
289
|
+
<ul>
|
|
290
|
+
${this.todos.map(t => html`<li>${t}</li>`)}
|
|
291
|
+
</ul>
|
|
292
|
+
<button @click=${this.addTodo}>Add</button>
|
|
293
|
+
</div>
|
|
294
|
+
`;
|
|
295
|
+
}
|
|
296
|
+
|
|
297
|
+
addTodo() {
|
|
298
|
+
this.todos = [...this.todos, 'New Task'];
|
|
299
|
+
// Differential rendering automatically updates only the new <li>!
|
|
300
|
+
}
|
|
301
|
+
}
|
|
302
|
+
```
|
|
303
|
+
|
|
304
|
+
**Key Changes:**
|
|
305
|
+
- **Remove `@part` entirely**
|
|
306
|
+
- Use **nested templates** with `.map()`
|
|
307
|
+
- **Differential rendering handles partial updates automatically**
|
|
308
|
+
- Must **reassign arrays** to trigger render: `this.todos = [...]`
|
|
309
|
+
|
|
310
|
+
---
|
|
311
|
+
|
|
312
|
+
### Step 5: Property and Boolean Attribute Binding
|
|
313
|
+
|
|
314
|
+
**New in v3.0.0:**
|
|
315
|
+
|
|
316
|
+
```typescript
|
|
317
|
+
import { element, property, render, html } from 'snice';
|
|
318
|
+
|
|
319
|
+
@element('custom-input')
|
|
320
|
+
class CustomInput extends HTMLElement {
|
|
321
|
+
@property()
|
|
322
|
+
value = '';
|
|
323
|
+
|
|
324
|
+
@property({ type: Boolean })
|
|
325
|
+
disabled = false;
|
|
326
|
+
|
|
327
|
+
@render()
|
|
328
|
+
renderContent() {
|
|
329
|
+
return html`
|
|
330
|
+
<input
|
|
331
|
+
.value=${this.value}
|
|
332
|
+
?disabled=${this.disabled}
|
|
333
|
+
@input=${this.handleInput}
|
|
334
|
+
/>
|
|
335
|
+
`;
|
|
336
|
+
}
|
|
337
|
+
|
|
338
|
+
handleInput(e: Event) {
|
|
339
|
+
this.value = (e.target as HTMLInputElement).value;
|
|
340
|
+
}
|
|
341
|
+
}
|
|
342
|
+
```
|
|
343
|
+
|
|
344
|
+
**Template Syntax:**
|
|
345
|
+
- `.value=${x}` - Sets **property**, not attribute (for form inputs)
|
|
346
|
+
- `?disabled=${bool}` - **Boolean attribute** (added if true, removed if false)
|
|
347
|
+
- `class=${x}` - Sets **attribute** (regular binding)
|
|
348
|
+
|
|
349
|
+
---
|
|
350
|
+
|
|
351
|
+
## Render Options
|
|
352
|
+
|
|
353
|
+
### Debouncing
|
|
354
|
+
|
|
355
|
+
Debounce renders for performance (useful for search inputs):
|
|
356
|
+
|
|
357
|
+
```typescript
|
|
358
|
+
@render({ debounce: 300 })
|
|
359
|
+
renderContent() {
|
|
360
|
+
return html`<input .value=${this.searchTerm} @input=${this.onSearch} />`;
|
|
361
|
+
}
|
|
362
|
+
|
|
363
|
+
onSearch(e: Event) {
|
|
364
|
+
this.searchTerm = (e.target as HTMLInputElement).value;
|
|
365
|
+
// Renders only after 300ms of no changes
|
|
366
|
+
}
|
|
367
|
+
```
|
|
368
|
+
|
|
369
|
+
### Throttling
|
|
370
|
+
|
|
371
|
+
Limit render frequency:
|
|
372
|
+
|
|
373
|
+
```typescript
|
|
374
|
+
@render({ throttle: 100 })
|
|
375
|
+
renderContent() {
|
|
376
|
+
return html`<div>Scroll: ${this.scrollY}</div>`;
|
|
377
|
+
}
|
|
378
|
+
```
|
|
379
|
+
|
|
380
|
+
### One-time Rendering
|
|
381
|
+
|
|
382
|
+
Disable auto-rendering (manual control):
|
|
383
|
+
|
|
384
|
+
```typescript
|
|
385
|
+
@render({ once: true })
|
|
386
|
+
renderContent() {
|
|
387
|
+
return html`<div>Static content</div>`;
|
|
388
|
+
}
|
|
389
|
+
|
|
390
|
+
updateManually() {
|
|
391
|
+
this.someData = 'new value';
|
|
392
|
+
this.renderContent(); // Explicit call to re-render
|
|
393
|
+
}
|
|
394
|
+
```
|
|
395
|
+
|
|
396
|
+
### Synchronous Rendering
|
|
397
|
+
|
|
398
|
+
Skip microtask batching (immediate updates):
|
|
399
|
+
|
|
400
|
+
```typescript
|
|
401
|
+
@render({ sync: true })
|
|
402
|
+
renderContent() {
|
|
403
|
+
return html`<div>${this.count}</div>`;
|
|
404
|
+
}
|
|
405
|
+
```
|
|
406
|
+
|
|
407
|
+
---
|
|
408
|
+
|
|
409
|
+
## Common Patterns
|
|
410
|
+
|
|
411
|
+
### Conditional Rendering
|
|
412
|
+
|
|
413
|
+
```typescript
|
|
414
|
+
@render()
|
|
415
|
+
renderContent() {
|
|
416
|
+
return html`
|
|
417
|
+
<div>
|
|
418
|
+
${this.isLoggedIn
|
|
419
|
+
? html`<span>Welcome, ${this.user.name}!</span>`
|
|
420
|
+
: html`<a href="/login">Login</a>`
|
|
421
|
+
}
|
|
422
|
+
</div>
|
|
423
|
+
`;
|
|
424
|
+
}
|
|
425
|
+
```
|
|
426
|
+
|
|
427
|
+
### Lists with Keys
|
|
428
|
+
|
|
429
|
+
For optimal performance, use unique keys when rendering lists:
|
|
430
|
+
|
|
431
|
+
```typescript
|
|
432
|
+
@render()
|
|
433
|
+
renderContent() {
|
|
434
|
+
return html`
|
|
435
|
+
<ul>
|
|
436
|
+
${this.items.map(item => html`
|
|
437
|
+
<li key=${item.id}>
|
|
438
|
+
${item.name}
|
|
439
|
+
<button @click=${() => this.remove(item.id)}>Remove</button>
|
|
440
|
+
</li>
|
|
441
|
+
`)}
|
|
442
|
+
</ul>
|
|
443
|
+
`;
|
|
444
|
+
}
|
|
445
|
+
```
|
|
446
|
+
|
|
447
|
+
### Nested Components
|
|
448
|
+
|
|
449
|
+
```typescript
|
|
450
|
+
@render()
|
|
451
|
+
renderContent() {
|
|
452
|
+
return html`
|
|
453
|
+
<div>
|
|
454
|
+
<user-card userId=${this.userId}></user-card>
|
|
455
|
+
<comment-list postId=${this.postId}></comment-list>
|
|
456
|
+
</div>
|
|
457
|
+
`;
|
|
458
|
+
}
|
|
459
|
+
```
|
|
460
|
+
|
|
461
|
+
---
|
|
462
|
+
|
|
463
|
+
## TypeScript Support
|
|
464
|
+
|
|
465
|
+
Update your imports:
|
|
466
|
+
|
|
467
|
+
```typescript
|
|
468
|
+
import {
|
|
469
|
+
element,
|
|
470
|
+
property,
|
|
471
|
+
render,
|
|
472
|
+
styles,
|
|
473
|
+
html,
|
|
474
|
+
css,
|
|
475
|
+
type TemplateResult,
|
|
476
|
+
type CSSResult,
|
|
477
|
+
type RenderOptions
|
|
478
|
+
} from 'snice';
|
|
479
|
+
```
|
|
480
|
+
|
|
481
|
+
Type your render methods:
|
|
482
|
+
|
|
483
|
+
```typescript
|
|
484
|
+
@render()
|
|
485
|
+
renderContent(): TemplateResult {
|
|
486
|
+
return html`<div>Content</div>`;
|
|
487
|
+
}
|
|
488
|
+
|
|
489
|
+
@styles()
|
|
490
|
+
componentStyles(): CSSResult {
|
|
491
|
+
return css`:host { display: block; }`;
|
|
492
|
+
}
|
|
493
|
+
```
|
|
494
|
+
|
|
495
|
+
---
|
|
496
|
+
|
|
497
|
+
## Testing
|
|
498
|
+
|
|
499
|
+
Update your tests to work with the new rendering system:
|
|
500
|
+
|
|
501
|
+
**Before (v2.x):**
|
|
502
|
+
```typescript
|
|
503
|
+
const el = document.createElement('my-element') as MyElement;
|
|
504
|
+
document.body.appendChild(el);
|
|
505
|
+
expect(el.shadowRoot!.innerHTML).toContain('expected content');
|
|
506
|
+
```
|
|
507
|
+
|
|
508
|
+
**After (v3.0.0):**
|
|
509
|
+
```typescript
|
|
510
|
+
const el = document.createElement('my-element') as MyElement;
|
|
511
|
+
document.body.appendChild(el);
|
|
512
|
+
|
|
513
|
+
// Wait for initial render
|
|
514
|
+
await el.ready;
|
|
515
|
+
|
|
516
|
+
// Check rendered content
|
|
517
|
+
expect(el.shadowRoot!.textContent).toContain('expected content');
|
|
518
|
+
|
|
519
|
+
// Trigger property change
|
|
520
|
+
el.someProperty = 'new value';
|
|
521
|
+
|
|
522
|
+
// Wait for next microtask (auto-render)
|
|
523
|
+
await new Promise(resolve => queueMicrotask(resolve));
|
|
524
|
+
|
|
525
|
+
// Verify differential update
|
|
526
|
+
expect(el.shadowRoot!.textContent).toContain('new value');
|
|
527
|
+
```
|
|
528
|
+
|
|
529
|
+
---
|
|
530
|
+
|
|
531
|
+
## Performance Benefits
|
|
532
|
+
|
|
533
|
+
### v2.x (Manual)
|
|
534
|
+
- ❌ Full `innerHTML` replacement on every update
|
|
535
|
+
- ❌ All event listeners destroyed and recreated
|
|
536
|
+
- ❌ Manual `@part` updates required
|
|
537
|
+
- ❌ No batching of updates
|
|
538
|
+
|
|
539
|
+
### v3.0.0 (Differential)
|
|
540
|
+
- ✅ **Only changed parts updated**
|
|
541
|
+
- ✅ Event listeners preserved and reused
|
|
542
|
+
- ✅ **Automatic batching** (microtask queue)
|
|
543
|
+
- ✅ **Debounce/throttle** built-in
|
|
544
|
+
- ✅ **10-100x faster** for large components
|
|
545
|
+
|
|
546
|
+
---
|
|
547
|
+
|
|
548
|
+
## Need Help?
|
|
549
|
+
|
|
550
|
+
- Check the updated [README.md](./README.md) for full examples
|
|
551
|
+
- See [docs/](./docs/) for detailed API documentation
|
|
552
|
+
- Open an issue on GitLab for migration questions
|
|
553
|
+
|
|
554
|
+
---
|
|
555
|
+
|
|
556
|
+
## Quick Reference
|
|
557
|
+
|
|
558
|
+
| v2.x | v3.0.0 |
|
|
559
|
+
|------|--------|
|
|
560
|
+
| `html()` method | `@render()` with `html\`\`` |
|
|
561
|
+
| `css()` method | `@styles()` with `css\`\`` |
|
|
562
|
+
| `@on('click', 'button')` | **Still works!** OR use `@click=${handler}` in template |
|
|
563
|
+
| `@on('keydown:Enter')` | **Still works!** OR use `@keydown:Enter=${handler}` in template |
|
|
564
|
+
| `@on('input', { debounce: 300 })` | **Still works!** (enhanced with throttle too) |
|
|
565
|
+
| `@part('name')` | Use `@render()` (differential rendering) |
|
|
566
|
+
| Manual `innerHTML` update | Automatic on property change |
|
|
567
|
+
| `this.shadowRoot!.innerHTML = ...` | Just update property: `this.count++` |
|
|
568
|
+
|
|
569
|
+
**Automatic differential rendering with powerful event handling!** 🚀
|