snice 4.10.0 → 4.11.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/adapters/react/carousel.d.ts +1 -0
- package/adapters/react/carousel.d.ts.map +1 -1
- package/adapters/react/carousel.js +1 -1
- package/adapters/react/carousel.js.map +1 -1
- package/adapters/react/carousel.tsx +2 -1
- package/bin/templates/CLAUDE.md +169 -113
- package/bin/templates/pwa/README.md +72 -94
- package/bin/templates/pwa/src/components/app-header.ts +218 -0
- package/bin/templates/pwa/src/components/notification-badge.ts +68 -0
- package/bin/templates/pwa/src/components/search-bar.ts +99 -0
- package/bin/templates/pwa/src/controllers/notification-controller.ts +42 -0
- package/bin/templates/pwa/src/guards/auth.ts +1 -1
- package/bin/templates/pwa/src/main.ts +19 -0
- package/bin/templates/pwa/src/pages/dashboard.ts +124 -23
- package/bin/templates/pwa/src/pages/data.ts +329 -0
- package/bin/templates/pwa/src/pages/notifications.ts +112 -30
- package/bin/templates/pwa/src/pages/profile.ts +86 -52
- package/bin/templates/pwa/src/pages/settings.ts +291 -0
- package/bin/templates/pwa/src/styles/global.css +12 -3
- package/dist/cdn/accordion/snice-accordion.js +1 -1
- package/dist/cdn/accordion/snice-accordion.min.js +1 -1
- package/dist/cdn/alert/snice-alert.js +1 -1
- package/dist/cdn/alert/snice-alert.min.js +1 -1
- package/dist/cdn/app-tiles/snice-app-tiles.js +1 -1
- package/dist/cdn/app-tiles/snice-app-tiles.min.js +1 -1
- package/dist/cdn/audio-recorder/snice-audio-recorder.js +1 -1
- package/dist/cdn/audio-recorder/snice-audio-recorder.min.js +1 -1
- package/dist/cdn/avatar/snice-avatar.js +1 -1
- package/dist/cdn/avatar/snice-avatar.min.js +1 -1
- package/dist/cdn/badge/snice-badge.js +1 -1
- package/dist/cdn/badge/snice-badge.min.js +1 -1
- package/dist/cdn/banner/snice-banner.js +1 -1
- package/dist/cdn/banner/snice-banner.min.js +1 -1
- package/dist/cdn/book/snice-book.js +1 -1
- package/dist/cdn/book/snice-book.min.js +1 -1
- package/dist/cdn/breadcrumbs/snice-breadcrumbs.js +1 -1
- package/dist/cdn/breadcrumbs/snice-breadcrumbs.min.js +1 -1
- package/dist/cdn/button/snice-button.js +1 -1
- package/dist/cdn/button/snice-button.min.js +1 -1
- package/dist/cdn/calendar/snice-calendar.js +1 -1
- package/dist/cdn/calendar/snice-calendar.min.js +1 -1
- package/dist/cdn/camera/README.md +1 -1
- package/dist/cdn/camera/snice-camera.js +1 -1
- package/dist/cdn/camera/snice-camera.min.js +1 -1
- package/dist/cdn/camera-annotate/snice-camera-annotate.js +1 -1
- package/dist/cdn/camera-annotate/snice-camera-annotate.min.js +1 -1
- package/dist/cdn/candlestick/snice-candlestick.js +1 -1
- package/dist/cdn/candlestick/snice-candlestick.min.js +1 -1
- package/dist/cdn/card/snice-card.js +1 -1
- package/dist/cdn/card/snice-card.min.js +1 -1
- package/dist/cdn/carousel/README.md +2 -2
- package/dist/cdn/carousel/snice-carousel.js +9 -3
- package/dist/cdn/carousel/snice-carousel.js.map +1 -1
- package/dist/cdn/carousel/snice-carousel.min.js +3 -3
- package/dist/cdn/carousel/snice-carousel.min.js.map +1 -1
- package/dist/cdn/chart/snice-chart.js +1 -1
- package/dist/cdn/chart/snice-chart.min.js +1 -1
- package/dist/cdn/chat/snice-chat.js +1 -1
- package/dist/cdn/chat/snice-chat.min.js +1 -1
- package/dist/cdn/checkbox/snice-checkbox.js +1 -1
- package/dist/cdn/checkbox/snice-checkbox.min.js +1 -1
- package/dist/cdn/chip/snice-chip.js +1 -1
- package/dist/cdn/chip/snice-chip.min.js +1 -1
- package/dist/cdn/code-block/snice-code-block.js +1 -1
- package/dist/cdn/code-block/snice-code-block.min.js +1 -1
- package/dist/cdn/color-display/snice-color-display.js +1 -1
- package/dist/cdn/color-display/snice-color-display.min.js +1 -1
- package/dist/cdn/color-picker/snice-color-picker.js +1 -1
- package/dist/cdn/color-picker/snice-color-picker.min.js +1 -1
- package/dist/cdn/command-palette/snice-command-palette.js +1 -1
- package/dist/cdn/command-palette/snice-command-palette.min.js +1 -1
- package/dist/cdn/comments/snice-comments.js +1 -1
- package/dist/cdn/comments/snice-comments.min.js +1 -1
- package/dist/cdn/countdown/snice-countdown.js +1 -1
- package/dist/cdn/countdown/snice-countdown.min.js +1 -1
- package/dist/cdn/cropper/snice-cropper.js +1 -1
- package/dist/cdn/cropper/snice-cropper.min.js +1 -1
- package/dist/cdn/date-picker/snice-date-picker.js +1 -1
- package/dist/cdn/date-picker/snice-date-picker.min.js +1 -1
- package/dist/cdn/diff/snice-diff.js +1 -1
- package/dist/cdn/diff/snice-diff.min.js +1 -1
- package/dist/cdn/divider/snice-divider.js +1 -1
- package/dist/cdn/divider/snice-divider.min.js +1 -1
- package/dist/cdn/doc/snice-doc.js +1 -1
- package/dist/cdn/doc/snice-doc.min.js +1 -1
- package/dist/cdn/draw/snice-draw.js +1 -1
- package/dist/cdn/draw/snice-draw.min.js +1 -1
- package/dist/cdn/drawer/snice-drawer.js +1 -1
- package/dist/cdn/drawer/snice-drawer.min.js +1 -1
- package/dist/cdn/empty-state/snice-empty-state.js +1 -1
- package/dist/cdn/empty-state/snice-empty-state.min.js +1 -1
- package/dist/cdn/file-gallery/snice-file-gallery.js +1 -1
- package/dist/cdn/file-gallery/snice-file-gallery.min.js +1 -1
- package/dist/cdn/file-upload/snice-file-upload.js +1 -1
- package/dist/cdn/file-upload/snice-file-upload.min.js +1 -1
- package/dist/cdn/flip-card/snice-flip-card.js +1 -1
- package/dist/cdn/flip-card/snice-flip-card.min.js +1 -1
- package/dist/cdn/flow/snice-flow.js +1 -1
- package/dist/cdn/flow/snice-flow.min.js +1 -1
- package/dist/cdn/funnel/snice-funnel.js +1 -1
- package/dist/cdn/funnel/snice-funnel.min.js +1 -1
- package/dist/cdn/gantt/README.md +1 -1
- package/dist/cdn/gantt/snice-gantt.js +1 -1
- package/dist/cdn/gantt/snice-gantt.min.js +1 -1
- package/dist/cdn/gauge/snice-gauge.js +1 -1
- package/dist/cdn/gauge/snice-gauge.min.js +1 -1
- package/dist/cdn/heatmap/snice-heatmap.js +1 -1
- package/dist/cdn/heatmap/snice-heatmap.min.js +1 -1
- package/dist/cdn/image/snice-image.js +1 -1
- package/dist/cdn/image/snice-image.min.js +1 -1
- package/dist/cdn/input/snice-input.js +1 -1
- package/dist/cdn/input/snice-input.min.js +1 -1
- package/dist/cdn/kanban/snice-kanban.js +1 -1
- package/dist/cdn/kanban/snice-kanban.min.js +1 -1
- package/dist/cdn/kpi/snice-kpi.js +1 -1
- package/dist/cdn/kpi/snice-kpi.min.js +1 -1
- package/dist/cdn/layout/snice-layout.js +1 -1
- package/dist/cdn/layout/snice-layout.min.js +1 -1
- package/dist/cdn/link/snice-link.js +1 -1
- package/dist/cdn/link/snice-link.min.js +1 -1
- package/dist/cdn/link-preview/snice-link-preview.js +1 -1
- package/dist/cdn/link-preview/snice-link-preview.min.js +1 -1
- package/dist/cdn/list/snice-list.js +1 -1
- package/dist/cdn/list/snice-list.min.js +1 -1
- package/dist/cdn/location/snice-location.js +1 -1
- package/dist/cdn/location/snice-location.min.js +1 -1
- package/dist/cdn/login/snice-login.js +1 -1
- package/dist/cdn/login/snice-login.min.js +1 -1
- package/dist/cdn/map/snice-map.js +1 -1
- package/dist/cdn/map/snice-map.min.js +1 -1
- package/dist/cdn/markdown/README.md +1 -1
- package/dist/cdn/markdown/snice-markdown.js +2 -2
- package/dist/cdn/markdown/snice-markdown.js.map +1 -1
- package/dist/cdn/markdown/snice-markdown.min.js +2 -2
- package/dist/cdn/markdown/snice-markdown.min.js.map +1 -1
- package/dist/cdn/masonry/snice-masonry.js +1 -1
- package/dist/cdn/masonry/snice-masonry.min.js +1 -1
- package/dist/cdn/menu/snice-menu.js +1 -1
- package/dist/cdn/menu/snice-menu.min.js +1 -1
- package/dist/cdn/modal/snice-modal.js +1 -1
- package/dist/cdn/modal/snice-modal.min.js +1 -1
- package/dist/cdn/music-player/snice-music-player.js +1 -1
- package/dist/cdn/music-player/snice-music-player.min.js +1 -1
- package/dist/cdn/nav/snice-nav.js +1 -1
- package/dist/cdn/nav/snice-nav.min.js +1 -1
- package/dist/cdn/network-graph/snice-network-graph.js +1 -1
- package/dist/cdn/network-graph/snice-network-graph.min.js +1 -1
- package/dist/cdn/notification-center/snice-notification-center.js +1 -1
- package/dist/cdn/notification-center/snice-notification-center.min.js +1 -1
- package/dist/cdn/org-chart/snice-org-chart.js +1 -1
- package/dist/cdn/org-chart/snice-org-chart.min.js +1 -1
- package/dist/cdn/pagination/snice-pagination.js +1 -1
- package/dist/cdn/pagination/snice-pagination.min.js +1 -1
- package/dist/cdn/paint/snice-paint.js +1 -1
- package/dist/cdn/paint/snice-paint.min.js +1 -1
- package/dist/cdn/pdf-viewer/README.md +2 -2
- package/dist/cdn/pdf-viewer/snice-pdf-viewer.js +72 -78
- package/dist/cdn/pdf-viewer/snice-pdf-viewer.js.map +1 -1
- package/dist/cdn/pdf-viewer/snice-pdf-viewer.min.js +3 -3
- package/dist/cdn/pdf-viewer/snice-pdf-viewer.min.js.map +1 -1
- package/dist/cdn/podcast-player/README.md +1 -1
- package/dist/cdn/podcast-player/snice-podcast-player.js +2 -2
- package/dist/cdn/podcast-player/snice-podcast-player.js.map +1 -1
- package/dist/cdn/podcast-player/snice-podcast-player.min.js +2 -2
- package/dist/cdn/podcast-player/snice-podcast-player.min.js.map +1 -1
- package/dist/cdn/pricing-table/snice-pricing-table.js +1 -1
- package/dist/cdn/pricing-table/snice-pricing-table.min.js +1 -1
- package/dist/cdn/progress/snice-progress.js +1 -1
- package/dist/cdn/progress/snice-progress.min.js +1 -1
- package/dist/cdn/qr-code/snice-qr-code.js +1 -1
- package/dist/cdn/qr-code/snice-qr-code.min.js +1 -1
- package/dist/cdn/qr-reader/snice-qr-reader.js +1 -1
- package/dist/cdn/qr-reader/snice-qr-reader.min.js +1 -1
- package/dist/cdn/radio/snice-radio.js +1 -1
- package/dist/cdn/radio/snice-radio.min.js +1 -1
- package/dist/cdn/rating/snice-rating.js +1 -1
- package/dist/cdn/rating/snice-rating.min.js +1 -1
- package/dist/cdn/recipe/snice-recipe.js +1 -1
- package/dist/cdn/recipe/snice-recipe.min.js +1 -1
- package/dist/cdn/runtime/README.md +1 -1
- package/dist/cdn/runtime/snice-runtime.esm.js +10 -3
- package/dist/cdn/runtime/snice-runtime.esm.js.map +1 -1
- package/dist/cdn/runtime/snice-runtime.esm.min.js +4 -4
- package/dist/cdn/runtime/snice-runtime.esm.min.js.map +1 -1
- package/dist/cdn/runtime/snice-runtime.js +10 -3
- package/dist/cdn/runtime/snice-runtime.js.map +1 -1
- package/dist/cdn/runtime/snice-runtime.min.js +4 -4
- package/dist/cdn/runtime/snice-runtime.min.js.map +1 -1
- package/dist/cdn/sankey/snice-sankey.js +1 -1
- package/dist/cdn/sankey/snice-sankey.min.js +1 -1
- package/dist/cdn/select/snice-select.js +1 -1
- package/dist/cdn/select/snice-select.min.js +1 -1
- package/dist/cdn/skeleton/snice-skeleton.js +1 -1
- package/dist/cdn/skeleton/snice-skeleton.min.js +1 -1
- package/dist/cdn/slider/snice-slider.js +1 -1
- package/dist/cdn/slider/snice-slider.min.js +1 -1
- package/dist/cdn/sortable/snice-sortable.js +1 -1
- package/dist/cdn/sortable/snice-sortable.min.js +1 -1
- package/dist/cdn/sparkline/snice-sparkline.js +1 -1
- package/dist/cdn/sparkline/snice-sparkline.min.js +1 -1
- package/dist/cdn/spinner/snice-spinner.js +1 -1
- package/dist/cdn/spinner/snice-spinner.min.js +1 -1
- package/dist/cdn/split-pane/snice-split-pane.js +1 -1
- package/dist/cdn/split-pane/snice-split-pane.min.js +1 -1
- package/dist/cdn/spotlight/snice-spotlight.js +1 -1
- package/dist/cdn/spotlight/snice-spotlight.min.js +1 -1
- package/dist/cdn/spreadsheet/snice-spreadsheet.js +1 -1
- package/dist/cdn/spreadsheet/snice-spreadsheet.min.js +1 -1
- package/dist/cdn/stepper/snice-stepper.js +1 -1
- package/dist/cdn/stepper/snice-stepper.min.js +1 -1
- package/dist/cdn/switch/snice-switch.js +1 -1
- package/dist/cdn/switch/snice-switch.min.js +1 -1
- package/dist/cdn/table/snice-table.js +1 -1
- package/dist/cdn/table/snice-table.min.js +1 -1
- package/dist/cdn/tabs/snice-tabs.js +1 -1
- package/dist/cdn/tabs/snice-tabs.min.js +1 -1
- package/dist/cdn/tag-input/snice-tag-input.js +1 -1
- package/dist/cdn/tag-input/snice-tag-input.min.js +1 -1
- package/dist/cdn/terminal/snice-terminal.js +1 -1
- package/dist/cdn/terminal/snice-terminal.min.js +1 -1
- package/dist/cdn/testimonial/snice-testimonial.js +1 -1
- package/dist/cdn/testimonial/snice-testimonial.min.js +1 -1
- package/dist/cdn/textarea/snice-textarea.js +1 -1
- package/dist/cdn/textarea/snice-textarea.min.js +1 -1
- package/dist/cdn/time-range-picker/snice-time-range-picker.js +1 -1
- package/dist/cdn/time-range-picker/snice-time-range-picker.min.js +1 -1
- package/dist/cdn/timeline/snice-timeline.js +1 -1
- package/dist/cdn/timeline/snice-timeline.min.js +1 -1
- package/dist/cdn/timer/snice-timer.js +1 -1
- package/dist/cdn/timer/snice-timer.min.js +1 -1
- package/dist/cdn/toast/snice-toast.js +1 -1
- package/dist/cdn/toast/snice-toast.min.js +1 -1
- package/dist/cdn/tooltip/snice-tooltip.js +1 -1
- package/dist/cdn/tooltip/snice-tooltip.min.js +1 -1
- package/dist/cdn/tree/snice-tree.js +1 -1
- package/dist/cdn/tree/snice-tree.min.js +1 -1
- package/dist/cdn/treemap/snice-treemap.js +1 -1
- package/dist/cdn/treemap/snice-treemap.min.js +1 -1
- package/dist/cdn/video-player/snice-video-player.js +1 -1
- package/dist/cdn/video-player/snice-video-player.min.js +1 -1
- package/dist/cdn/virtual-scroller/snice-virtual-scroller.js +1 -1
- package/dist/cdn/virtual-scroller/snice-virtual-scroller.min.js +1 -1
- package/dist/cdn/waterfall/snice-waterfall.js +1 -1
- package/dist/cdn/waterfall/snice-waterfall.min.js +1 -1
- package/dist/cdn/weather/snice-weather.js +1 -1
- package/dist/cdn/weather/snice-weather.min.js +1 -1
- package/dist/components/carousel/snice-carousel.js +8 -2
- package/dist/components/carousel/snice-carousel.js.map +1 -1
- package/dist/components/markdown/snice-markdown.js +1 -1
- package/dist/components/markdown/snice-markdown.js.map +1 -1
- package/dist/components/pdf-viewer/snice-pdf-viewer.d.ts +9 -8
- package/dist/components/pdf-viewer/snice-pdf-viewer.js +71 -77
- package/dist/components/pdf-viewer/snice-pdf-viewer.js.map +1 -1
- package/dist/components/podcast-player/snice-podcast-player.js +1 -1
- package/dist/components/podcast-player/snice-podcast-player.js.map +1 -1
- package/dist/index.cjs +8 -1
- package/dist/index.cjs.map +1 -1
- package/dist/index.esm.js +8 -1
- package/dist/index.esm.js.map +1 -1
- package/dist/index.iife.js +8 -1
- package/dist/index.iife.js.map +1 -1
- package/dist/symbols.cjs +1 -1
- package/dist/symbols.esm.js +1 -1
- package/dist/transitions.cjs +1 -1
- package/dist/transitions.esm.js +1 -1
- package/docs/ai/patterns.md +1 -1
- package/docs/routing.md +2 -2
- package/package.json +1 -1
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"carousel.d.ts","sourceRoot":"","sources":["carousel.tsx"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,SAAS,CAAC;AAE9C;;GAEG;AACH,MAAM,WAAW,aAAc,SAAQ,cAAc;IACnD,WAAW,CAAC,EAAE,GAAG,CAAC;IAClB,QAAQ,CAAC,EAAE,GAAG,CAAC;IACf,gBAAgB,CAAC,EAAE,GAAG,CAAC;IACvB,iBAAiB,CAAC,EAAE,GAAG,CAAC;IACxB,IAAI,CAAC,EAAE,GAAG,CAAC;IACX,YAAY,CAAC,EAAE,GAAG,CAAC;IACnB,cAAc,CAAC,EAAE,GAAG,CAAC;IACrB,aAAa,CAAC,EAAE,GAAG,CAAC;IACpB,YAAY,CAAC,EAAE,GAAG,CAAC;
|
|
1
|
+
{"version":3,"file":"carousel.d.ts","sourceRoot":"","sources":["carousel.tsx"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,SAAS,CAAC;AAE9C;;GAEG;AACH,MAAM,WAAW,aAAc,SAAQ,cAAc;IACnD,WAAW,CAAC,EAAE,GAAG,CAAC;IAClB,QAAQ,CAAC,EAAE,GAAG,CAAC;IACf,gBAAgB,CAAC,EAAE,GAAG,CAAC;IACvB,iBAAiB,CAAC,EAAE,GAAG,CAAC;IACxB,IAAI,CAAC,EAAE,GAAG,CAAC;IACX,YAAY,CAAC,EAAE,GAAG,CAAC;IACnB,cAAc,CAAC,EAAE,GAAG,CAAC;IACrB,aAAa,CAAC,EAAE,GAAG,CAAC;IACpB,YAAY,CAAC,EAAE,GAAG,CAAC;IACnB,UAAU,CAAC,EAAE,GAAG,CAAC;CAElB;AAED;;;;;;;;;;;;;;;GAeG;AACH,eAAO,MAAM,QAAQ,4GAKnB,CAAC"}
|
|
@@ -17,7 +17,7 @@ import { createReactAdapter } from './wrapper';
|
|
|
17
17
|
*/
|
|
18
18
|
export const Carousel = createReactAdapter({
|
|
19
19
|
tagName: 'snice-carousel',
|
|
20
|
-
properties: ["activeIndex", "autoplay", "autoplayInterval", "autoplayDirection", "loop", "showControls", "showIndicators", "slidesPerView", "spaceBetween"],
|
|
20
|
+
properties: ["activeIndex", "autoplay", "autoplayInterval", "autoplayDirection", "loop", "showControls", "showIndicators", "slidesPerView", "spaceBetween", "slideCount"],
|
|
21
21
|
events: {},
|
|
22
22
|
formAssociated: false
|
|
23
23
|
});
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"carousel.js","sourceRoot":"","sources":["carousel.tsx"],"names":[],"mappings":"AAAA,OAAO,EAAE,kBAAkB,EAAE,MAAM,WAAW,CAAC;
|
|
1
|
+
{"version":3,"file":"carousel.js","sourceRoot":"","sources":["carousel.tsx"],"names":[],"mappings":"AAAA,OAAO,EAAE,kBAAkB,EAAE,MAAM,WAAW,CAAC;AAoB/C;;;;;;;;;;;;;;;GAeG;AACH,MAAM,CAAC,MAAM,QAAQ,GAAG,kBAAkB,CAAgB;IACxD,OAAO,EAAE,gBAAgB;IACzB,UAAU,EAAE,CAAC,aAAa,EAAC,UAAU,EAAC,kBAAkB,EAAC,mBAAmB,EAAC,MAAM,EAAC,cAAc,EAAC,gBAAgB,EAAC,eAAe,EAAC,cAAc,EAAC,YAAY,CAAC;IAChK,MAAM,EAAE,EAAE;IACV,cAAc,EAAE,KAAK;CACtB,CAAC,CAAC"}
|
|
@@ -14,6 +14,7 @@ export interface CarouselProps extends SniceBaseProps {
|
|
|
14
14
|
showIndicators?: any;
|
|
15
15
|
slidesPerView?: any;
|
|
16
16
|
spaceBetween?: any;
|
|
17
|
+
slideCount?: any;
|
|
17
18
|
|
|
18
19
|
}
|
|
19
20
|
|
|
@@ -35,7 +36,7 @@ export interface CarouselProps extends SniceBaseProps {
|
|
|
35
36
|
*/
|
|
36
37
|
export const Carousel = createReactAdapter<CarouselProps>({
|
|
37
38
|
tagName: 'snice-carousel',
|
|
38
|
-
properties: ["activeIndex","autoplay","autoplayInterval","autoplayDirection","loop","showControls","showIndicators","slidesPerView","spaceBetween"],
|
|
39
|
+
properties: ["activeIndex","autoplay","autoplayInterval","autoplayDirection","loop","showControls","showIndicators","slidesPerView","spaceBetween","slideCount"],
|
|
39
40
|
events: {},
|
|
40
41
|
formAssociated: false
|
|
41
42
|
});
|
package/bin/templates/CLAUDE.md
CHANGED
|
@@ -1,14 +1,33 @@
|
|
|
1
1
|
# Snice Project - AI Assistant Guide
|
|
2
2
|
|
|
3
|
+
## IMMEDIATELY: Install the Snice MCP Server
|
|
4
|
+
|
|
5
|
+
Snice ships an MCP server that gives you access to component docs, decorator reference, code validation, and component scaffolding. Install it before doing any work:
|
|
6
|
+
|
|
7
|
+
```bash
|
|
8
|
+
claude mcp add snice -- npx snice mcp
|
|
9
|
+
```
|
|
10
|
+
|
|
11
|
+
This gives you these tools:
|
|
12
|
+
- `list_components` — List all available UI components
|
|
13
|
+
- `get_component_docs` — Get docs for a specific component
|
|
14
|
+
- `get_decorator_docs` — Get decorator reference
|
|
15
|
+
- `get_overview` — Framework overview
|
|
16
|
+
- `generate_component` — Scaffold new components
|
|
17
|
+
- `search_docs` — Search documentation
|
|
18
|
+
- `validate_code` — Check code for common Snice mistakes
|
|
19
|
+
|
|
20
|
+
**Use these tools instead of guessing.** If you're unsure about a component's API, call `get_component_docs`. If you're writing a new component, call `generate_component` for the scaffold.
|
|
21
|
+
|
|
3
22
|
## Documentation Location
|
|
4
23
|
|
|
5
|
-
AI-optimized docs shipped in: `node_modules/snice/docs/ai/`
|
|
24
|
+
AI-optimized docs are shipped in: `node_modules/snice/docs/ai/`
|
|
6
25
|
|
|
7
26
|
**Read these files:**
|
|
8
|
-
- `api.md`
|
|
9
|
-
- `patterns.md`
|
|
10
|
-
- `architecture.md`
|
|
11
|
-
- `components/*.md`
|
|
27
|
+
- `api.md` — Complete API reference
|
|
28
|
+
- `patterns.md` — Usage examples for every feature
|
|
29
|
+
- `architecture.md` — System design
|
|
30
|
+
- `components/*.md` — Component docs (read only as needed)
|
|
12
31
|
|
|
13
32
|
## Project Structure
|
|
14
33
|
|
|
@@ -26,154 +45,190 @@ src/
|
|
|
26
45
|
styles/ # Global CSS
|
|
27
46
|
```
|
|
28
47
|
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
- **
|
|
33
|
-
- **
|
|
34
|
-
- **
|
|
35
|
-
- **
|
|
36
|
-
- **
|
|
48
|
+
## Critical Architecture Rules
|
|
49
|
+
|
|
50
|
+
**Separation of concerns — DO NOT violate these:**
|
|
51
|
+
- **Elements** — Pure visual presentation. NO fetch(), NO API calls, NO business logic. Receive data via properties, emit events for actions.
|
|
52
|
+
- **Pages** — Orchestrate elements. Handle routing, call APIs, coordinate data flow. Most app logic lives here.
|
|
53
|
+
- **Controllers** — Attach to elements via `controller="name"`. Add reusable non-visual behavior (data loading, validation). NOT global services.
|
|
54
|
+
- **Services** — Stateless functions for business logic, API calls. Importable anywhere.
|
|
55
|
+
- **Daemons** — Stateful lifecycle classes (WebSocket connections, polling intervals).
|
|
56
|
+
- **Middleware** — Composable fetch middleware (auth headers, retry, error handling).
|
|
57
|
+
|
|
58
|
+
## Snice is NOT Lit
|
|
37
59
|
|
|
38
|
-
|
|
60
|
+
Do NOT import from `lit` or extend `LitElement`. Snice has its own decorator system:
|
|
61
|
+
- No `@customElement()` — use `@element('tag-name')`
|
|
62
|
+
- No `@state()` — use plain class fields for internal state, `@property()` for attributes
|
|
63
|
+
- No `render()` lifecycle method — use `@render()` decorator
|
|
64
|
+
- No `static styles` — use `@styles()` decorator
|
|
65
|
+
- No `reflect: true` — attributes sync automatically
|
|
66
|
+
|
|
67
|
+
## Decorators Quick Reference
|
|
39
68
|
|
|
40
69
|
```typescript
|
|
41
70
|
// Class decorators
|
|
42
|
-
@
|
|
43
|
-
@
|
|
44
|
-
@controller('name')
|
|
45
|
-
@layout('name')
|
|
46
|
-
|
|
47
|
-
//
|
|
48
|
-
@property() name = 'default'
|
|
49
|
-
@
|
|
50
|
-
@
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
@
|
|
54
|
-
@
|
|
55
|
-
@
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
@
|
|
59
|
-
@
|
|
60
|
-
|
|
61
|
-
|
|
71
|
+
@element('tag-name') // Define custom element
|
|
72
|
+
@page({ tag, routes, guards?, placard? }) // Routable page (from Router(), NOT 'snice')
|
|
73
|
+
@controller('name') // Behavior module
|
|
74
|
+
@layout('name') // Page wrapper
|
|
75
|
+
|
|
76
|
+
// Properties & reactivity
|
|
77
|
+
@property({ type?, attribute? }) name = 'default' // Reactive attribute
|
|
78
|
+
@watch('propName') // React to property changes: (oldVal, newVal, propName)
|
|
79
|
+
@context() // Receive router Context on navigation
|
|
80
|
+
|
|
81
|
+
// Rendering
|
|
82
|
+
@render() // Declarative template: return html`...`
|
|
83
|
+
@render({ once: true }) // Imperative: render once, update via @watch + @query
|
|
84
|
+
@styles() // Scoped CSS: return css`...`
|
|
85
|
+
|
|
86
|
+
// DOM
|
|
87
|
+
@query('selector') // Single shadow DOM element
|
|
88
|
+
@queryAll('selector') // Multiple shadow DOM elements
|
|
89
|
+
|
|
90
|
+
// Lifecycle
|
|
91
|
+
@ready() // After first render
|
|
92
|
+
@dispose() // On disconnect
|
|
93
|
+
|
|
94
|
+
// Events
|
|
95
|
+
@on('click', 'button') // Event listener
|
|
96
|
+
@on('input', 'input', { debounce: 300 }) // Debounced
|
|
97
|
+
@on('keydown:ctrl+s') // Keyboard shortcut
|
|
98
|
+
@dispatch('event-name') // Fire CustomEvent (detail = return value)
|
|
99
|
+
|
|
100
|
+
// Communication
|
|
101
|
+
@request('channel') // Async generator: const result = await (yield payload)
|
|
102
|
+
@respond('channel') // Handle requests: receives payload, returns response
|
|
103
|
+
|
|
104
|
+
// Observers
|
|
105
|
+
@observe('resize', '.el') // ResizeObserver
|
|
106
|
+
@observe('intersection', '.el') // IntersectionObserver
|
|
107
|
+
@observe('media:(min-width: 768px)') // Media query
|
|
108
|
+
@observe('mutation:childList', '.el') // MutationObserver
|
|
62
109
|
```
|
|
63
110
|
|
|
64
|
-
##
|
|
111
|
+
## Router — Common Mistakes
|
|
65
112
|
|
|
66
|
-
**Element:**
|
|
67
113
|
```typescript
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
@styles()
|
|
81
|
-
componentStyles() {
|
|
82
|
-
return css`:host { display: block; }`;
|
|
83
|
-
}
|
|
84
|
-
}
|
|
114
|
+
// router.ts — CORRECT setup
|
|
115
|
+
import { Router } from 'snice';
|
|
116
|
+
|
|
117
|
+
export const { page, navigate, initialize } = Router({
|
|
118
|
+
target: '#app',
|
|
119
|
+
type: 'hash', // REQUIRED: 'hash' or 'pushstate'
|
|
120
|
+
layout: 'app-shell',
|
|
121
|
+
context: { user: null, theme: 'light' }
|
|
122
|
+
});
|
|
123
|
+
|
|
124
|
+
// pages import `page` from './router', NOT from 'snice'
|
|
125
|
+
import { page } from '../router';
|
|
85
126
|
```
|
|
86
127
|
|
|
87
|
-
**
|
|
128
|
+
**Guards signature — TWO parameters:**
|
|
88
129
|
```typescript
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
async load() {
|
|
95
|
-
const user = await fetch(`/api/users/${this.id}`).then(r => r.json());
|
|
96
|
-
}
|
|
97
|
-
}
|
|
130
|
+
// CORRECT:
|
|
131
|
+
const isAuthenticated = (context: any, params: any) => context.principal?.isAuthenticated === true;
|
|
132
|
+
|
|
133
|
+
// WRONG:
|
|
134
|
+
const isAuth = (ctx) => ctx.isAuthenticated; // Missing params, wrong property access
|
|
98
135
|
```
|
|
99
136
|
|
|
100
|
-
**
|
|
137
|
+
**Navigation — use hash URLs:**
|
|
101
138
|
```typescript
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
element: HTMLElement;
|
|
139
|
+
// CORRECT:
|
|
140
|
+
html`<a href="/#/users/123">View User</a>`
|
|
105
141
|
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
142
|
+
// WRONG:
|
|
143
|
+
navigate('/users/123') // Does not change the URL
|
|
144
|
+
```
|
|
109
145
|
|
|
110
|
-
|
|
146
|
+
## Native Element Controllers
|
|
111
147
|
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
}
|
|
148
|
+
Controllers work on ANY HTML element, not just custom elements:
|
|
149
|
+
```typescript
|
|
150
|
+
import { useNativeElementControllers } from 'snice';
|
|
151
|
+
useNativeElementControllers(); // Call once in main.ts
|
|
115
152
|
|
|
116
|
-
//
|
|
153
|
+
// Then use in HTML:
|
|
154
|
+
// <form controller="checkout-form">...</form>
|
|
155
|
+
// <div controller="data-loader">...</div>
|
|
117
156
|
```
|
|
118
157
|
|
|
119
|
-
|
|
120
|
-
```typescript
|
|
121
|
-
html`
|
|
122
|
-
${items.map(item => html`
|
|
123
|
-
<li key=${item.id}>${item.name}</li>
|
|
124
|
-
`)}
|
|
125
|
-
`
|
|
126
|
-
```
|
|
158
|
+
## Templates
|
|
127
159
|
|
|
128
|
-
**Conditionals:**
|
|
129
160
|
```typescript
|
|
130
161
|
html`
|
|
131
|
-
|
|
162
|
+
<!-- Attribute binding -->
|
|
163
|
+
<div class="${cls}">
|
|
164
|
+
|
|
165
|
+
<!-- Property binding (objects/arrays) -->
|
|
166
|
+
<my-el .items=${array}>
|
|
167
|
+
|
|
168
|
+
<!-- Boolean attribute toggle -->
|
|
169
|
+
<button ?disabled=${isLoading}>
|
|
170
|
+
|
|
171
|
+
<!-- Event handler (auto-bound to this) -->
|
|
172
|
+
<button @click=${this.handleClick}>
|
|
173
|
+
|
|
174
|
+
<!-- Keyboard shortcut -->
|
|
175
|
+
<input @keydown:Enter=${this.submit}>
|
|
176
|
+
<input @keydown:ctrl+s=${this.save}>
|
|
177
|
+
|
|
178
|
+
<!-- Conditionals -->
|
|
179
|
+
<if ${isLoggedIn}><span>Welcome</span></if>
|
|
180
|
+
<case ${status}>
|
|
181
|
+
<when value="loading"><spinner></spinner></when>
|
|
182
|
+
<when value="error"><p>Error</p></when>
|
|
183
|
+
<default><p>Ready</p></default>
|
|
184
|
+
</case>
|
|
185
|
+
|
|
186
|
+
<!-- Lists with keys -->
|
|
187
|
+
${items.map(item => html`<li key=${item.id}>${item.name}</li>`)}
|
|
132
188
|
`
|
|
133
189
|
```
|
|
134
190
|
|
|
135
|
-
## Communication
|
|
191
|
+
## Communication Patterns
|
|
136
192
|
|
|
137
193
|
- **Parent → Child:** Properties (`.prop=${value}`)
|
|
138
194
|
- **Child → Parent:** Events (`@dispatch`)
|
|
139
|
-
- **Element ↔ Controller:** Request/Response (`@request
|
|
140
|
-
- **Global State:** Context (`@context()`)
|
|
195
|
+
- **Element ↔ Controller:** Request/Response (`@request` / `@respond`)
|
|
196
|
+
- **Global State:** Context (`@context()` — receives updates on navigation and `ctx.update()`)
|
|
141
197
|
|
|
142
|
-
|
|
143
|
-
All component events use unprefixed names (e.g., `tab-change`, `menu-open`):
|
|
198
|
+
**@request uses async generators:**
|
|
144
199
|
```typescript
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
200
|
+
@request('fetch-user')
|
|
201
|
+
async *fetchUser(id: string): any {
|
|
202
|
+
const user = await (yield { id }); // yield = send, await = receive
|
|
203
|
+
return user;
|
|
204
|
+
}
|
|
205
|
+
// Usage: const user = await this.fetchUser('123');
|
|
151
206
|
```
|
|
152
207
|
|
|
153
|
-
##
|
|
208
|
+
## Imperative Rendering
|
|
154
209
|
|
|
155
|
-
|
|
210
|
+
For fixed-structure templates where only content changes:
|
|
156
211
|
```typescript
|
|
157
|
-
|
|
158
|
-
html`<
|
|
159
|
-
window.location.hash = '#/users/123'
|
|
212
|
+
@render({ once: true })
|
|
213
|
+
template() { return html`<div class="content"></div>`; }
|
|
160
214
|
|
|
161
|
-
|
|
162
|
-
|
|
215
|
+
@query('.content') $content!: HTMLElement;
|
|
216
|
+
|
|
217
|
+
@watch('data')
|
|
218
|
+
updateContent() {
|
|
219
|
+
if (!this.$content) return; // Guard: watcher fires before first render
|
|
220
|
+
this.$content.textContent = this.data;
|
|
221
|
+
}
|
|
163
222
|
```
|
|
164
|
-
`router.navigate()` does not change the URL.
|
|
165
223
|
|
|
166
224
|
## Common Mistakes
|
|
167
225
|
|
|
168
|
-
**Controllers are NOT global services.** They attach to elements
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
**
|
|
173
|
-
|
|
174
|
-
**Context must be mutated then signaled.** After changing `ctx.application`, call `ctx.update()` to signal subscribers. Pages need `@context()` to get context reference.
|
|
175
|
-
|
|
176
|
-
**@property is for parent-provided attributes.** Internal component state should be regular properties, not decorated. Only use `@property()` when the value comes from a parent element via attributes.
|
|
226
|
+
- **Controllers are NOT global services.** They attach to elements. Use `services/` or `utils/` for shared logic.
|
|
227
|
+
- **@request/@respond is NOT a service bus.** Element-to-controller communication only.
|
|
228
|
+
- **Context must be mutated then signaled.** Change `ctx.application.theme = 'dark'`, then call `ctx.update()`.
|
|
229
|
+
- **@property is for parent-provided attributes.** Internal state should be plain class fields.
|
|
230
|
+
- **Events use kebab-case:** `count-changed`, not `countChanged`. Access via `e.detail`.
|
|
231
|
+
- **No `reflect` option.** Attributes sync automatically for `:host([attr])` CSS selectors.
|
|
177
232
|
|
|
178
233
|
## Build Commands
|
|
179
234
|
|
|
@@ -181,4 +236,5 @@ router.navigate('/users/123')
|
|
|
181
236
|
npm run dev # Dev server
|
|
182
237
|
npm run build # Production build
|
|
183
238
|
npm run type-check # TypeScript check
|
|
239
|
+
npm run test # Run tests (if configured)
|
|
184
240
|
```
|
|
@@ -4,14 +4,21 @@ A Progressive Web App (PWA) built with [Snice](https://github.com/sniceio/snice)
|
|
|
4
4
|
|
|
5
5
|
## Features
|
|
6
6
|
|
|
7
|
-
-
|
|
8
|
-
-
|
|
9
|
-
-
|
|
10
|
-
-
|
|
11
|
-
-
|
|
12
|
-
-
|
|
13
|
-
-
|
|
14
|
-
-
|
|
7
|
+
- **JWT Authentication** - Token-based auth with automatic refresh and middleware
|
|
8
|
+
- **Protected Routes** - Guards with `(context, params) => boolean` signature
|
|
9
|
+
- **Middleware Pattern** - Composable fetch middleware (auth headers, error handling, retry)
|
|
10
|
+
- **PWA Ready** - Service worker, offline support, installable
|
|
11
|
+
- **Live Notifications** - WebSocket daemon with real-time updates and badge counter
|
|
12
|
+
- **Theme Switching** - Light, dark, and system theme with persistence
|
|
13
|
+
- **Data Listing** - Filterable table with debounced search
|
|
14
|
+
- **Controllers** - Notification controller with `@respond` pattern
|
|
15
|
+
- **Native Element Controllers** - Attach controllers to any HTML element
|
|
16
|
+
- **Imperative Rendering** - `@render({ once: true })` with `@watch` + `@query`
|
|
17
|
+
- **Observers** - `@observe('resize')`, `@observe('media:(...)')` for responsive behavior
|
|
18
|
+
- **Keyboard Shortcuts** - Ctrl+S to save settings, Ctrl+Backspace to clear notifications, Escape to close menus
|
|
19
|
+
- **Snice Components** - Pre-built UI (cards, alerts, avatars, switches, badges, dividers, tabs)
|
|
20
|
+
- **Type-Safe** - Full TypeScript support
|
|
21
|
+
- **Fast Build** - Vite + SWC
|
|
15
22
|
|
|
16
23
|
## Getting Started
|
|
17
24
|
|
|
@@ -41,97 +48,69 @@ npm run type-check
|
|
|
41
48
|
|
|
42
49
|
```
|
|
43
50
|
src/
|
|
44
|
-
|
|
51
|
+
components/ # @element decorated UI components
|
|
52
|
+
app-header.ts # Nav bar with user avatar, menu, @context
|
|
53
|
+
search-bar.ts # Debounced search with @on('input', { debounce: 300 })
|
|
54
|
+
notification-badge.ts # Imperative rendering with @render({ once: true })
|
|
55
|
+
controllers/ # @controller decorated behavior modules
|
|
56
|
+
notification-controller.ts # @respond('get-notifications')
|
|
57
|
+
pages/ # Routable pages (@page decorator)
|
|
58
|
+
login.ts # Login form with @respond('login-user')
|
|
59
|
+
dashboard.ts # Stats, @observe('media:...'), notification counter
|
|
60
|
+
profile.ts # User info, @dispatch, @observe, <case>/<when>
|
|
61
|
+
notifications.ts # Live feed, filters, @watch, keyboard shortcuts
|
|
62
|
+
settings.ts # Theme toggle, form bindings, @context, Ctrl+S save
|
|
63
|
+
data.ts # Data table, search-bar, @observe('resize'), filters
|
|
45
64
|
services/ # Business logic (auth, storage, jwt)
|
|
46
|
-
middleware/
|
|
65
|
+
middleware/ # Fetch middleware (auth, error, retry)
|
|
47
66
|
daemons/ # Lifecycle-managed classes (notifications WebSocket)
|
|
48
67
|
guards/ # Route guards (auth)
|
|
49
68
|
types/ # TypeScript types
|
|
50
|
-
|
|
51
|
-
styles/ # Global styles
|
|
52
|
-
```
|
|
53
|
-
|
|
54
|
-
## Architecture Patterns
|
|
55
|
-
|
|
56
|
-
### Context-Aware Fetcher
|
|
57
|
-
|
|
58
|
-
Built-in middleware system with context access:
|
|
59
|
-
|
|
60
|
-
```typescript
|
|
61
|
-
// fetcher.ts - Setup
|
|
62
|
-
import { ContextAwareFetcher } from 'snice';
|
|
63
|
-
|
|
64
|
-
const fetcher = new ContextAwareFetcher();
|
|
65
|
-
fetcher.use('request', authMiddleware);
|
|
66
|
-
fetcher.use('response', errorMiddleware);
|
|
67
|
-
|
|
68
|
-
// Middleware with context access
|
|
69
|
-
export async function authMiddleware(
|
|
70
|
-
this: Context,
|
|
71
|
-
request: Request,
|
|
72
|
-
next: () => Promise<Response>
|
|
73
|
-
): Promise<Response> {
|
|
74
|
-
const token = getToken();
|
|
75
|
-
if (token) {
|
|
76
|
-
request.headers.set('Authorization', `Bearer ${token}`);
|
|
77
|
-
}
|
|
78
|
-
return next();
|
|
79
|
-
}
|
|
80
|
-
|
|
81
|
-
// Usage in pages via ctx.fetch()
|
|
82
|
-
async loadData() {
|
|
83
|
-
const response = await this.ctx.fetch('/api/data');
|
|
84
|
-
const data = await response.json();
|
|
85
|
-
}
|
|
86
|
-
```
|
|
87
|
-
|
|
88
|
-
### Daemons for Lifecycle Management
|
|
89
|
-
|
|
90
|
-
Use daemons for resources that need start/stop/dispose:
|
|
91
|
-
|
|
92
|
-
```typescript
|
|
93
|
-
const daemon = getNotificationsDaemon();
|
|
94
|
-
daemon.start(); // In main.ts
|
|
95
|
-
|
|
96
|
-
// In component
|
|
97
|
-
const unsubscribe = daemon.subscribe((notification) => {
|
|
98
|
-
console.log(notification);
|
|
99
|
-
});
|
|
100
|
-
|
|
101
|
-
// Cleanup
|
|
102
|
-
unsubscribe();
|
|
103
|
-
```
|
|
104
|
-
|
|
105
|
-
### Route Guards
|
|
106
|
-
|
|
107
|
-
Protect routes with guards:
|
|
108
|
-
|
|
109
|
-
```typescript
|
|
110
|
-
import { authGuard } from './guards/auth';
|
|
111
|
-
|
|
112
|
-
@page({
|
|
113
|
-
tag: 'dashboard-page',
|
|
114
|
-
routes: ['/dashboard'],
|
|
115
|
-
guards: [authGuard]
|
|
116
|
-
})
|
|
117
|
-
export class DashboardPage extends HTMLElement {
|
|
118
|
-
// ...
|
|
119
|
-
}
|
|
69
|
+
styles/ # Global styles with dark/light theme support
|
|
120
70
|
```
|
|
121
71
|
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
}
|
|
134
|
-
|
|
72
|
+
## Snice Features Demonstrated
|
|
73
|
+
|
|
74
|
+
### Decorators
|
|
75
|
+
|
|
76
|
+
| Decorator | Used In |
|
|
77
|
+
|-----------|---------|
|
|
78
|
+
| `@page` | All pages |
|
|
79
|
+
| `@element` | app-header, search-bar, notification-badge |
|
|
80
|
+
| `@controller` | notification-controller |
|
|
81
|
+
| `@property` | Multiple components |
|
|
82
|
+
| `@render` | All components |
|
|
83
|
+
| `@render({ once: true })` | notification-badge (imperative) |
|
|
84
|
+
| `@styles` | All components |
|
|
85
|
+
| `@context` | dashboard, profile, settings, app-header |
|
|
86
|
+
| `@watch` | notification-badge, notifications page |
|
|
87
|
+
| `@query` | notification-badge, app-header |
|
|
88
|
+
| `@on` | search-bar, settings, notifications, app-header |
|
|
89
|
+
| `@dispatch` | search-bar, profile, settings, app-header |
|
|
90
|
+
| `@respond` | login page, notification-controller |
|
|
91
|
+
| `@observe` | dashboard (media), profile (media), data (resize) |
|
|
92
|
+
| `@ready` | dashboard, notifications, notification-badge |
|
|
93
|
+
| `@dispose` | dashboard, notifications, notification-badge |
|
|
94
|
+
|
|
95
|
+
### Template Features
|
|
96
|
+
|
|
97
|
+
| Feature | Used In |
|
|
98
|
+
|---------|---------|
|
|
99
|
+
| `<if>` conditionals | dashboard, notifications, data, app-header |
|
|
100
|
+
| `<case>/<when>/<default>` | profile, notifications, data |
|
|
101
|
+
| `.prop` binding | search-bar, settings |
|
|
102
|
+
| `?attr` boolean binding | settings (switch) |
|
|
103
|
+
| `@event` binding | All components |
|
|
104
|
+
| `@keydown:modifier` | settings (Ctrl+S), app-header (Escape), notifications (Ctrl+Backspace) |
|
|
105
|
+
| `key` attribute | notifications list, data table |
|
|
106
|
+
|
|
107
|
+
### Architecture Patterns
|
|
108
|
+
|
|
109
|
+
- **Context-Aware Fetcher** with auth, error, and retry middleware
|
|
110
|
+
- **Daemons** for WebSocket lifecycle management
|
|
111
|
+
- **Guards** with `(context, params) => boolean` signature
|
|
112
|
+
- **Request/Response** for element-to-controller communication
|
|
113
|
+
- **Native Element Controllers** via `useNativeElementControllers()`
|
|
135
114
|
|
|
136
115
|
## Customization
|
|
137
116
|
|
|
@@ -146,7 +125,6 @@ export async function login(credentials: LoginCredentials) {
|
|
|
146
125
|
headers: { 'Content-Type': 'application/json' },
|
|
147
126
|
body: JSON.stringify(credentials)
|
|
148
127
|
});
|
|
149
|
-
|
|
150
128
|
const data = await response.json();
|
|
151
129
|
setToken(data.token);
|
|
152
130
|
setUser(data.user);
|