snice 7.0.2 → 7.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/.agents/skills/snice/SKILL.md +4 -0
- package/.agents/skills/snice/references/core-kitchen-sink.ts +39 -1
- package/README.md +59 -14
- package/adapters/react/SniceProvider.js +2 -2
- package/adapters/react/SniceRouter.js +2 -2
- package/adapters/react/matchRoute.js +2 -2
- package/adapters/react/useRequestHandler.js +2 -2
- package/bin/analyzer-contracts.js +6 -1
- package/bin/postinstall.js +59 -0
- package/bin/project-analyzer.js +466 -5
- package/bin/snice.js +3 -0
- package/dist/app-context.d.ts +11 -0
- package/dist/cdn/accordion/snice-accordion.js +2 -2
- package/dist/cdn/action-bar/snice-action-bar.js +2 -2
- package/dist/cdn/activity-feed/snice-activity-feed.js +2 -2
- package/dist/cdn/alert/snice-alert.js +2 -2
- package/dist/cdn/app-tiles/snice-app-tiles.js +2 -2
- package/dist/cdn/approval-flow/snice-approval-flow.js +2 -2
- package/dist/cdn/audio-recorder/snice-audio-recorder.js +2 -2
- package/dist/cdn/availability/snice-availability.js +2 -2
- package/dist/cdn/avatar/snice-avatar.js +2 -2
- package/dist/cdn/avatar-group/snice-avatar-group.js +2 -2
- package/dist/cdn/badge/snice-badge.js +2 -2
- package/dist/cdn/banner/snice-banner.js +2 -2
- package/dist/cdn/binpack/snice-binpack.js +2 -2
- package/dist/cdn/book/snice-book.js +2 -2
- package/dist/cdn/booking/snice-booking.js +2 -2
- package/dist/cdn/breadcrumbs/snice-breadcrumbs.js +2 -2
- package/dist/cdn/button/snice-button.js +2 -2
- package/dist/cdn/calendar/snice-calendar.js +2 -2
- package/dist/cdn/camera/snice-camera.js +2 -2
- package/dist/cdn/camera-annotate/snice-camera-annotate.js +2 -2
- package/dist/cdn/candlestick/snice-candlestick.js +2 -2
- package/dist/cdn/card/snice-card.js +2 -2
- package/dist/cdn/carousel/snice-carousel.js +2 -2
- package/dist/cdn/cart/snice-cart.js +2 -2
- package/dist/cdn/chart/snice-chart.js +2 -2
- package/dist/cdn/chat/snice-chat.js +2 -2
- package/dist/cdn/checkbox/snice-checkbox.js +2 -2
- package/dist/cdn/chip/snice-chip.js +2 -2
- package/dist/cdn/code-block/snice-code-block.js +2 -2
- package/dist/cdn/color-display/snice-color-display.js +2 -2
- package/dist/cdn/color-picker/snice-color-picker.js +2 -2
- package/dist/cdn/command-palette/snice-command-palette.js +2 -2
- package/dist/cdn/comments/snice-comments.js +2 -2
- package/dist/cdn/countdown/snice-countdown.js +2 -2
- package/dist/cdn/cropper/snice-cropper.js +2 -2
- package/dist/cdn/data-card/snice-data-card.js +2 -2
- package/dist/cdn/date-picker/snice-date-picker.js +2 -2
- package/dist/cdn/date-range-picker/snice-date-range-picker.js +2 -2
- package/dist/cdn/date-time-picker/snice-date-time-picker.js +2 -2
- package/dist/cdn/diff/snice-diff.js +2 -2
- package/dist/cdn/divider/snice-divider.js +2 -2
- package/dist/cdn/doc/snice-doc.js +2 -2
- package/dist/cdn/draw/snice-draw.js +2 -2
- package/dist/cdn/drawer/snice-drawer.js +2 -2
- package/dist/cdn/empty-state/snice-empty-state.js +2 -2
- package/dist/cdn/estimate/snice-estimate.js +2 -2
- package/dist/cdn/file-gallery/snice-file-gallery.js +2 -2
- package/dist/cdn/file-upload/snice-file-upload.js +2 -2
- package/dist/cdn/flip-card/snice-flip-card.js +2 -2
- package/dist/cdn/flow/snice-flow.js +2 -2
- package/dist/cdn/form-layout/snice-form-layout.js +2 -2
- package/dist/cdn/funnel/snice-funnel.js +2 -2
- package/dist/cdn/gantt/snice-gantt.js +2 -2
- package/dist/cdn/gauge/snice-gauge.js +2 -2
- package/dist/cdn/grid/snice-grid.js +2 -2
- package/dist/cdn/heatmap/snice-heatmap.js +2 -2
- package/dist/cdn/image/snice-image.js +2 -2
- package/dist/cdn/input/snice-input.js +2 -2
- package/dist/cdn/invoice/snice-invoice.js +2 -2
- package/dist/cdn/kanban/snice-kanban.js +2 -2
- package/dist/cdn/key-value/snice-key-value.js +2 -2
- package/dist/cdn/kpi/snice-kpi.js +2 -2
- package/dist/cdn/layout/README.md +17 -2
- package/dist/cdn/layout/snice-layout.js +1656 -11
- package/dist/cdn/layout/snice-layout.js.map +1 -1
- package/dist/cdn/layout/snice-layout.min.js +379 -2
- package/dist/cdn/layout/snice-layout.min.js.map +1 -1
- package/dist/cdn/leaderboard/snice-leaderboard.js +2 -2
- package/dist/cdn/link/snice-link.js +2 -2
- package/dist/cdn/link-preview/snice-link-preview.js +2 -2
- package/dist/cdn/list/snice-list.js +2 -2
- package/dist/cdn/location/snice-location.js +2 -2
- package/dist/cdn/login/snice-login.js +2 -2
- package/dist/cdn/map/snice-map.js +2 -2
- package/dist/cdn/markdown/snice-markdown.js +2 -2
- package/dist/cdn/masonry/snice-masonry.js +2 -2
- package/dist/cdn/menu/snice-menu.js +2 -2
- package/dist/cdn/message-strip/snice-message-strip.js +2 -2
- package/dist/cdn/modal/snice-modal.js +2 -2
- package/dist/cdn/music-player/snice-music-player.js +2 -2
- package/dist/cdn/nav/snice-nav.js +2 -2
- package/dist/cdn/network-graph/snice-network-graph.js +2 -2
- package/dist/cdn/notification-center/snice-notification-center.js +2 -2
- package/dist/cdn/order-tracker/snice-order-tracker.js +2 -2
- package/dist/cdn/org-chart/snice-org-chart.js +2 -2
- package/dist/cdn/pagination/snice-pagination.js +2 -2
- package/dist/cdn/paint/snice-paint.js +2 -2
- package/dist/cdn/pdf-viewer/snice-pdf-viewer.js +2 -2
- package/dist/cdn/permission-matrix/snice-permission-matrix.js +2 -2
- package/dist/cdn/podcast-player/snice-podcast-player.js +2 -2
- package/dist/cdn/popover/snice-popover.js +2 -2
- package/dist/cdn/pricing-table/snice-pricing-table.js +2 -2
- package/dist/cdn/product-card/snice-product-card.js +2 -2
- package/dist/cdn/progress/snice-progress.js +2 -2
- package/dist/cdn/progress-ring/snice-progress-ring.js +2 -2
- package/dist/cdn/qr-code/snice-qr-code.js +2 -2
- package/dist/cdn/qr-reader/snice-qr-reader.js +2 -2
- package/dist/cdn/radio/snice-radio.js +2 -2
- package/dist/cdn/range-slider/snice-range-slider.js +2 -2
- package/dist/cdn/rating/snice-rating.js +2 -2
- package/dist/cdn/receipt/snice-receipt.js +2 -2
- package/dist/cdn/recipe/snice-recipe.js +3 -3
- package/dist/cdn/recipe/snice-recipe.js.map +1 -1
- package/dist/cdn/recipe/snice-recipe.min.js +1 -1
- package/dist/cdn/recipe/snice-recipe.min.js.map +1 -1
- package/dist/cdn/runtime/README.md +2 -2
- package/dist/cdn/runtime/snice-runtime.esm.js +3725 -3336
- package/dist/cdn/runtime/snice-runtime.esm.js.map +1 -1
- package/dist/cdn/runtime/snice-runtime.esm.min.js +1 -1
- package/dist/cdn/runtime/snice-runtime.esm.min.js.map +1 -1
- package/dist/cdn/runtime/snice-runtime.js +3727 -3335
- package/dist/cdn/runtime/snice-runtime.js.map +1 -1
- package/dist/cdn/runtime/snice-runtime.min.js +1 -1
- package/dist/cdn/runtime/snice-runtime.min.js.map +1 -1
- package/dist/cdn/sankey/snice-sankey.js +2 -2
- package/dist/cdn/segmented-control/snice-segmented-control.js +2 -2
- package/dist/cdn/select/snice-select.js +2 -2
- package/dist/cdn/skeleton/snice-skeleton.js +2 -2
- package/dist/cdn/slider/snice-slider.js +2 -2
- package/dist/cdn/sortable/snice-sortable.js +2 -2
- package/dist/cdn/sparkline/snice-sparkline.js +2 -2
- package/dist/cdn/spinner/snice-spinner.js +2 -2
- package/dist/cdn/split-button/snice-split-button.js +2 -2
- package/dist/cdn/split-pane/snice-split-pane.js +2 -2
- package/dist/cdn/spotlight/snice-spotlight.js +2 -2
- package/dist/cdn/stat-group/snice-stat-group.js +2 -2
- package/dist/cdn/step-input/snice-step-input.js +2 -2
- package/dist/cdn/stepper/snice-stepper.js +2 -2
- package/dist/cdn/switch/snice-switch.js +2 -2
- package/dist/cdn/table/README.md +6 -2
- package/dist/cdn/table/snice-table.esm.js +366 -56
- package/dist/cdn/table/snice-table.esm.js.map +1 -1
- package/dist/cdn/table/snice-table.esm.min.js +107 -46
- package/dist/cdn/table/snice-table.esm.min.js.map +1 -1
- package/dist/cdn/table/snice-table.js +367 -59
- package/dist/cdn/table/snice-table.js.map +1 -1
- package/dist/cdn/table/snice-table.min.js +155 -94
- package/dist/cdn/table/snice-table.min.js.map +1 -1
- package/dist/cdn/tabs/snice-tabs.js +2 -2
- package/dist/cdn/tag/snice-tag.js +2 -2
- package/dist/cdn/tag-input/snice-tag-input.js +2 -2
- package/dist/cdn/terminal/snice-terminal.js +3 -2
- package/dist/cdn/terminal/snice-terminal.js.map +1 -1
- package/dist/cdn/terminal/snice-terminal.min.js +1 -0
- package/dist/cdn/terminal/snice-terminal.min.js.map +1 -1
- package/dist/cdn/testimonial/snice-testimonial.js +2 -2
- package/dist/cdn/textarea/snice-textarea.js +2 -2
- package/dist/cdn/time-picker/snice-time-picker.js +2 -2
- package/dist/cdn/time-range-picker/snice-time-range-picker.js +2 -2
- package/dist/cdn/timeline/snice-timeline.js +2 -2
- package/dist/cdn/timer/snice-timer.js +2 -2
- package/dist/cdn/toast/snice-toast.js +2 -2
- package/dist/cdn/tooltip/snice-tooltip.js +2 -2
- package/dist/cdn/tree/snice-tree.js +2 -2
- package/dist/cdn/treemap/snice-treemap.js +2 -2
- package/dist/cdn/user-card/snice-user-card.js +2 -2
- package/dist/cdn/video-player/README.md +1 -1
- package/dist/cdn/video-player/snice-video-player.js +3 -2
- package/dist/cdn/video-player/snice-video-player.js.map +1 -1
- package/dist/cdn/video-player/snice-video-player.min.js +1 -0
- package/dist/cdn/video-player/snice-video-player.min.js.map +1 -1
- package/dist/cdn/virtual-scroller/snice-virtual-scroller.js +2 -2
- package/dist/cdn/waterfall/snice-waterfall.js +2 -2
- package/dist/cdn/weather/snice-weather.js +2 -2
- package/dist/cdn/work-order/snice-work-order.js +2 -2
- package/dist/components/recipe/snice-recipe.js +1 -1
- package/dist/components/recipe/snice-recipe.js.map +1 -1
- package/dist/components/table/snice-table.d.ts +1 -0
- package/dist/components/table/snice-table.js +18 -2
- package/dist/components/table/snice-table.js.map +1 -1
- package/dist/components/table/table-tree-data.js +1 -0
- package/dist/components/table/table-tree-data.js.map +1 -1
- package/dist/components/terminal/snice-terminal.js +1 -0
- package/dist/components/terminal/snice-terminal.js.map +1 -1
- package/dist/components/video-player/snice-video-player.js +1 -0
- package/dist/components/video-player/snice-video-player.js.map +1 -1
- package/dist/context-provider.d.ts +16 -0
- package/dist/daemon-target.d.ts +10 -0
- package/dist/daemon.d.ts +10 -0
- package/dist/index.cjs +3721 -3329
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.ts +3 -0
- package/dist/index.esm.js +3719 -3330
- package/dist/index.esm.js.map +1 -1
- package/dist/index.iife.js +3721 -3329
- package/dist/index.iife.js.map +1 -1
- package/dist/keyboard-filter.d.ts +25 -0
- package/dist/on.d.ts +1 -1
- package/dist/parts.d.ts +0 -17
- package/dist/react/SniceProvider.js +2 -2
- package/dist/react/SniceRouter.js +2 -2
- package/dist/react/index.js +2 -2
- package/dist/react/matchRoute.js +2 -2
- package/dist/react/useRequestHandler.js +2 -2
- package/dist/request-response.d.ts +9 -1
- package/dist/symbols.cjs +11 -2
- package/dist/symbols.cjs.map +1 -1
- package/dist/symbols.d.ts +3 -0
- package/dist/symbols.esm.js +9 -3
- package/dist/symbols.esm.js.map +1 -1
- package/dist/testing.d.ts +1 -1
- package/dist/transitions.cjs +2 -2
- package/dist/transitions.esm.js +2 -2
- package/dist/types/app-context.d.ts +9 -58
- package/dist/types/daemon.d.ts +8 -0
- package/dist/types/dispatch-options.d.ts +2 -0
- package/dist/types/index.d.ts +1 -0
- package/dist/types/on-options.d.ts +5 -0
- package/dist/types/request-options.d.ts +2 -0
- package/dist/types/respond-options.d.ts +2 -0
- package/docs/ai/DEVELOPMENT.md +15 -1
- package/docs/ai/README.md +5 -1
- package/docs/ai/api.md +13 -4
- package/docs/ai/architecture.md +50 -1
- package/docs/ai/cli.md +9 -0
- package/docs/ai/components/avatar.md +8 -8
- package/docs/ai/components/breadcrumbs.md +2 -1
- package/docs/ai/components/button.md +2 -7
- package/docs/ai/components/calendar.md +1 -1
- package/docs/ai/components/camera.md +1 -1
- package/docs/ai/components/chart.md +3 -1
- package/docs/ai/components/code-block.md +2 -2
- package/docs/ai/components/date-picker.md +5 -19
- package/docs/ai/components/date-range-picker.md +4 -12
- package/docs/ai/components/draw.md +5 -5
- package/docs/ai/components/drawer.md +4 -4
- package/docs/ai/components/form-layout.md +2 -0
- package/docs/ai/components/icons.md +7 -16
- package/docs/ai/components/key-value.md +3 -22
- package/docs/ai/components/layout.md +8 -12
- package/docs/ai/components/leaderboard.md +2 -2
- package/docs/ai/components/link-preview.md +4 -3
- package/docs/ai/components/login.md +11 -0
- package/docs/ai/components/markdown.md +7 -0
- package/docs/ai/components/masonry.md +6 -0
- package/docs/ai/components/menu.md +1 -1
- package/docs/ai/components/modal.md +7 -0
- package/docs/ai/components/notification-center.md +5 -4
- package/docs/ai/components/radio.md +7 -0
- package/docs/ai/components/rating.md +3 -3
- package/docs/ai/components/select.md +4 -13
- package/docs/ai/components/spotlight.md +2 -0
- package/docs/ai/components/table.md +1 -4
- package/docs/ai/components/tag-input.md +6 -0
- package/docs/ai/components/terminal.md +6 -0
- package/docs/ai/components/tooltip.md +10 -16
- package/docs/ai/components/tree.md +2 -2
- package/docs/ai/components/video-player.md +5 -0
- package/docs/ai/components/waterfall.md +7 -0
- package/docs/ai/daemons.md +80 -0
- package/docs/ai/decorators.md +6 -4
- package/docs/ai/events.md +35 -0
- package/docs/ai/patterns.md +45 -1
- package/docs/ai/request-response.md +26 -9
- package/docs/ai/routing.md +16 -1
- package/docs/cli.md +7 -0
- package/docs/components/breadcrumbs.md +2 -1
- package/docs/components/calendar.md +1 -1
- package/docs/components/camera.md +1 -1
- package/docs/components/chart.md +1 -1
- package/docs/components/code-block.md +13 -4
- package/docs/components/color-picker.md +6 -5
- package/docs/components/date-time-picker.md +14 -0
- package/docs/components/diff.md +2 -1
- package/docs/components/draw.md +5 -5
- package/docs/components/drawer.md +4 -4
- package/docs/components/input.md +1 -0
- package/docs/components/layout.md +20 -22
- package/docs/components/leaderboard.md +10 -3
- package/docs/components/link-preview.md +11 -9
- package/docs/components/login.md +4 -0
- package/docs/components/menu.md +1 -1
- package/docs/components/modal.md +1 -0
- package/docs/components/nav.md +1 -0
- package/docs/components/network-graph.md +1 -0
- package/docs/components/notification-center.md +2 -1
- package/docs/components/product-card.md +1 -0
- package/docs/components/qr-reader.md +1 -0
- package/docs/components/rating.md +4 -4
- package/docs/components/select.md +1 -0
- package/docs/components/spotlight.md +2 -0
- package/docs/components/tabs.md +1 -0
- package/docs/components/terminal.md +3 -0
- package/docs/components/textarea.md +1 -1
- package/docs/components/time-picker.md +14 -0
- package/docs/components/tooltip.md +2 -0
- package/docs/components/tree.md +2 -2
- package/docs/daemons.md +200 -0
- package/docs/events.md +92 -2
- package/docs/request-response.md +20 -13
- package/docs/routing.md +25 -1
- package/package.json +6 -4
|
@@ -103,3 +103,10 @@ Only the newly selected radio emits. The old member is silently unchecked. Direc
|
|
|
103
103
|
Slot: `suffix`.
|
|
104
104
|
|
|
105
105
|
CSS parts: `input`, `radio`, `dot`, `spinner`, `content`, `label`, `description`.
|
|
106
|
+
|
|
107
|
+
## Accessibility
|
|
108
|
+
|
|
109
|
+
- Native radio input drives keyboard and AT behavior; one roving tab stop per named group
|
|
110
|
+
- Visible label text associated with the native control; external `<label for>` supports association, focus, activation, cancellation
|
|
111
|
+
- Required group validity and native labels exposed through `ElementInternals`
|
|
112
|
+
- Visible keyboard focus indicator; `aria-invalid` reflects explicit or calculated group invalidity
|
|
@@ -7,7 +7,7 @@ Interactive star rating input with full/half precision, custom icons, and keyboa
|
|
|
7
7
|
```typescript
|
|
8
8
|
value: number = 0;
|
|
9
9
|
max: number = 5;
|
|
10
|
-
icon: string = '
|
|
10
|
+
icon: string = 'star'; // catalogue name, emoji, URL, or image file
|
|
11
11
|
emptyIcon: string = ''; // attr empty-icon; empty falls back to icon
|
|
12
12
|
size: 'small'|'medium'|'large' = 'medium';
|
|
13
13
|
readonly: boolean = false;
|
|
@@ -20,8 +20,8 @@ precision: 'full'|'half' = 'full';
|
|
|
20
20
|
|
|
21
21
|
## CSS Custom Properties
|
|
22
22
|
|
|
23
|
-
- `--rating-color` - Filled star color (`
|
|
24
|
-
- `--rating-color-empty` - Empty star color (`var(--snice-color-
|
|
23
|
+
- `--rating-color` - Filled star color (`rgb(245 158 11)`; not theme-derived)
|
|
24
|
+
- `--rating-color-empty` - Empty star color (`var(--snice-color-text-tertiary)`)
|
|
25
25
|
- `--rating-size` - Star size (auto-set by `size`: small=1rem, medium=1.5rem, large=2rem)
|
|
26
26
|
|
|
27
27
|
## CSS Parts
|
|
@@ -14,14 +14,8 @@ Customizable dropdown selection with single/multiple, search, editable input, an
|
|
|
14
14
|
```typescript
|
|
15
15
|
value: string = ''; // Live; comma-separated for multiple
|
|
16
16
|
defaultValue: string = ''; // attr: value; authored/reset default
|
|
17
|
-
disabled: boolean = false;
|
|
18
|
-
|
|
19
|
-
invalid: boolean = false;
|
|
20
|
-
readonly: boolean = false;
|
|
21
|
-
loading: boolean = false;
|
|
22
|
-
multiple: boolean = false;
|
|
23
|
-
searchable: boolean = false;
|
|
24
|
-
clearable: boolean = false;
|
|
17
|
+
disabled | required | invalid | readonly | loading: boolean = false;
|
|
18
|
+
multiple | searchable | clearable: boolean = false;
|
|
25
19
|
editable: boolean = false; // Text input trigger instead of button
|
|
26
20
|
allowFreeText: boolean = false; // attr: allow-free-text
|
|
27
21
|
remote: boolean = false; // Remote search via @request('select/search')
|
|
@@ -37,11 +31,8 @@ placeholder: string = 'Select an option';
|
|
|
37
31
|
maxHeight: string = '200px'; // attr: max-height
|
|
38
32
|
options: SelectOption[] = []; // JS only, works alongside <snice-option> children
|
|
39
33
|
readonly labels: NodeList | null; // Current explicit/wrapping external labels
|
|
40
|
-
readonly type: 'select-one' | 'select-multiple';
|
|
41
|
-
readonly
|
|
42
|
-
readonly validity: ValidityState;
|
|
43
|
-
readonly validationMessage: string;
|
|
44
|
-
readonly willValidate: boolean;
|
|
34
|
+
readonly type: 'select-one' | 'select-multiple'; form: HTMLFormElement | null;
|
|
35
|
+
readonly validity: ValidityState; validationMessage: string; willValidate: boolean;
|
|
45
36
|
```
|
|
46
37
|
|
|
47
38
|
### snice-option
|
|
@@ -29,6 +29,7 @@ interface SpotlightStep {
|
|
|
29
29
|
- `spotlight-step` → `{ index, step }`
|
|
30
30
|
- `spotlight-end` → `void`
|
|
31
31
|
- `spotlight-skip` → `{ index }`
|
|
32
|
+
- `spotlight-target-missing` → `{ index, step }` — step target gone (e.g. route change); popover stops instead of pointing at nothing
|
|
32
33
|
|
|
33
34
|
## CSS Custom Properties
|
|
34
35
|
|
|
@@ -55,6 +56,7 @@ spotlight.start();
|
|
|
55
56
|
|
|
56
57
|
spotlight.addEventListener('spotlight-end', () => console.log('Tour completed'));
|
|
57
58
|
spotlight.addEventListener('spotlight-skip', (e) => console.log(`Skipped at ${e.detail.index}`));
|
|
59
|
+
spotlight.addEventListener('spotlight-target-missing', (e) => console.warn('Missing target', e.detail.step.target));
|
|
58
60
|
```
|
|
59
61
|
|
|
60
62
|
## CSS Parts
|
|
@@ -124,10 +124,7 @@ type CellStyle={backgroundColor?:string;color?:string;fontWeight?:'normal'|'bold
|
|
|
124
124
|
|
|
125
125
|
## CSS Parts
|
|
126
126
|
|
|
127
|
-
- `body` -
|
|
128
|
-
- `filter-button` - Column filter trigger
|
|
129
|
-
- `sort-indicator` - Column sort direction indicator
|
|
130
|
-
- `<snice-table>`: `superheader`, `controls`, `toolbar`, `pagination` (no native header/body/cell parts); `<snice-row>`: `container`, `checkbox-cell`, `cell`; cells: `content`; actions: `action-button`; JSON: `toggle`; tag: `tag`; link/email/phone/location: `link`
|
|
127
|
+
- `<snice-table>`: `body`, `superheader`, `controls`, `toolbar`, `pagination`, `filter-button` (column filter trigger), `sort-indicator` (sort direction); `<snice-row>`: `container`, `checkbox-cell`, `cell`; cells: `content`; actions: `action-button`; JSON: `toggle`; tag: `tag`; link/email/phone/location: `link`
|
|
131
128
|
|
|
132
129
|
## CSS Custom Properties
|
|
133
130
|
|
|
@@ -87,3 +87,9 @@ tagInput.addEventListener('tag-change', (e) => {
|
|
|
87
87
|
console.log('Tags:', e.detail.value);
|
|
88
88
|
});
|
|
89
89
|
```
|
|
90
|
+
|
|
91
|
+
## Accessibility
|
|
92
|
+
|
|
93
|
+
- `label` supplies the input's accessible name
|
|
94
|
+
- Adding, removing, and selecting tags are all reachable by keyboard (see Keyboard Navigation)
|
|
95
|
+
- Focus returns to the input after a tag is added or removed
|
|
@@ -23,6 +23,12 @@ showTimestamps: boolean = false; // attr: show-timestamps
|
|
|
23
23
|
- `getHistory()` - Get command history
|
|
24
24
|
- `clearHistory()` - Clear command history
|
|
25
25
|
|
|
26
|
+
Streaming API — feed raw chunks without splitting on newlines; a trailing partial line stays live and grows until a newline commits it:
|
|
27
|
+
|
|
28
|
+
- `appendChunk(chunk, type?)` - Append a raw chunk
|
|
29
|
+
- `pipeFrom(source, type?)` - Stream an `AsyncIterable<string>` or `ReadableStream<string|Uint8Array>`; returns `Promise<void>`
|
|
30
|
+
- `commitLiveLine()` - Force the live buffer to become a finished line
|
|
31
|
+
|
|
26
32
|
## Events
|
|
27
33
|
|
|
28
34
|
- `terminal-command` -> `{ command, args }` - Command entered
|
|
@@ -90,19 +90,13 @@ Observer for `tooltip` attribute on any element. No wrapper element -- safe insi
|
|
|
90
90
|
|
|
91
91
|
### CSS Variable API
|
|
92
92
|
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
| `--tooltip-strict-positioning` | (false) | `true` to disable auto-flip |
|
|
104
|
-
| `--tooltip-bg` | `hsl(0 0% 20%)` | Background color |
|
|
105
|
-
| `--tooltip-color` | `white` | Text color |
|
|
106
|
-
| `--tooltip-padding` | `8px 12px` | Content padding |
|
|
107
|
-
| `--tooltip-radius` | `6px` | Border radius |
|
|
108
|
-
| `--tooltip-font-size` | `14px` | Font size |
|
|
93
|
+
- `--tooltip-position` (`top`) — top/bottom/left/right + `-start`/`-end`
|
|
94
|
+
- `--tooltip-trigger` (`hover`) — hover, click, focus
|
|
95
|
+
- `--tooltip-delay` (`0`) / `--tooltip-hide-delay` (`0`) — show / hide delay (ms)
|
|
96
|
+
- `--tooltip-offset` (`12`) — distance from trigger (px)
|
|
97
|
+
- `--tooltip-arrow` (shown) — `none` to hide; `--tooltip-arrow-size` (`6px`) sizes it
|
|
98
|
+
- `--tooltip-max-width` (`250`) — max width (px)
|
|
99
|
+
- `--tooltip-z-index` (`10000`)
|
|
100
|
+
- `--tooltip-strict-positioning` (false) — `true` disables auto-flip
|
|
101
|
+
- `--tooltip-bg` (`hsl(0 0% 20%)`) background / `--tooltip-color` (`white`) text color
|
|
102
|
+
- `--tooltip-padding` (`8px 12px`) content padding, `--tooltip-radius` (`6px`), `--tooltip-font-size` (`14px`)
|
|
@@ -11,8 +11,8 @@ showCheckboxes: boolean = false; // attr: show-checkboxes
|
|
|
11
11
|
showIcons: boolean = true; // attr: show-icons
|
|
12
12
|
expandOnClick: boolean = false; // attr: expand-on-click
|
|
13
13
|
nodes: TreeNode[] = [];
|
|
14
|
-
selectedNodes: string[] = []; //
|
|
15
|
-
checkedNodes: string[] = []; //
|
|
14
|
+
selectedNodes: string[] = []; // JS-only; no attribute
|
|
15
|
+
checkedNodes: string[] = []; // JS-only; no attribute
|
|
16
16
|
|
|
17
17
|
interface TreeNode {
|
|
18
18
|
id: string;
|
|
@@ -78,6 +78,11 @@ duration: number; // read-only
|
|
|
78
78
|
- ArrowRight/ArrowLeft: Seek forward/backward 5s
|
|
79
79
|
- ArrowUp/ArrowDown: Volume up/down 10%
|
|
80
80
|
|
|
81
|
+
## Accessibility
|
|
82
|
+
|
|
83
|
+
- Controls carry ARIA labels; current time, duration, and playback state are exposed to AT
|
|
84
|
+
- Transitions respect `prefers-reduced-motion`
|
|
85
|
+
|
|
81
86
|
## Basic Usage
|
|
82
87
|
|
|
83
88
|
```html
|
|
@@ -58,3 +58,10 @@ chart.addEventListener('bar-click', (e) => {
|
|
|
58
58
|
console.log(`Clicked: ${e.detail.item.label} (${e.detail.item.value})`);
|
|
59
59
|
});
|
|
60
60
|
```
|
|
61
|
+
|
|
62
|
+
## Accessibility
|
|
63
|
+
|
|
64
|
+
- Bars carry data-visualization roles, are focusable, and activate by keyboard
|
|
65
|
+
- `showValues` exposes value labels as screen-reader text
|
|
66
|
+
- Bar types distinguishable by color *and* value label, not color alone
|
|
67
|
+
- Animations respect `prefers-reduced-motion`
|
|
@@ -0,0 +1,80 @@
|
|
|
1
|
+
# Daemons
|
|
2
|
+
|
|
3
|
+
Human reference: `docs/daemons.md`.
|
|
4
|
+
|
|
5
|
+
Ordinary explicitly constructed stateful objects with app-owned lifecycles.
|
|
6
|
+
`@daemon` adds per-instance Snice communication; it never constructs, caches,
|
|
7
|
+
globally registers, starts, or stops an instance.
|
|
8
|
+
|
|
9
|
+
```typescript
|
|
10
|
+
@daemon
|
|
11
|
+
class SessionDaemon {
|
|
12
|
+
session: Session | null = null;
|
|
13
|
+
|
|
14
|
+
@respond('get-session')
|
|
15
|
+
getSession() { return this.session; }
|
|
16
|
+
|
|
17
|
+
@on('set-session')
|
|
18
|
+
setSession(e: CustomEvent<Session>) {
|
|
19
|
+
this.session = e.detail;
|
|
20
|
+
this.changed();
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
@dispatch('session-changed')
|
|
24
|
+
changed() { return this.session; }
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
const session = new SessionDaemon();
|
|
28
|
+
const release = provideContext(appRoot, { daemons: { session } });
|
|
29
|
+
```
|
|
30
|
+
|
|
31
|
+
Context contract:
|
|
32
|
+
|
|
33
|
+
```typescript
|
|
34
|
+
type DaemonMap = Readonly<Record<string, object>>;
|
|
35
|
+
|
|
36
|
+
interface AppContext {
|
|
37
|
+
readonly daemons?: DaemonMap;
|
|
38
|
+
[key: string]: unknown;
|
|
39
|
+
}
|
|
40
|
+
```
|
|
41
|
+
|
|
42
|
+
Extend `AppContext` to type application-specific fields; Snice assigns meaning
|
|
43
|
+
only to `daemons`.
|
|
44
|
+
|
|
45
|
+
Router automatically provides its `context` beneath `target`. Non-router apps
|
|
46
|
+
call `provideContext(root, context)`. `getContext(elementOrController)` returns
|
|
47
|
+
the raw visible app context.
|
|
48
|
+
|
|
49
|
+
Consumer; no daemon implementation import:
|
|
50
|
+
|
|
51
|
+
```typescript
|
|
52
|
+
@request<Session | null>('get-session', { daemon: 'session' })
|
|
53
|
+
async *load(): Response<Session | null> { return yield {}; }
|
|
54
|
+
|
|
55
|
+
@dispatch('set-session', { daemon: 'session' })
|
|
56
|
+
set(session: Session) { return session; }
|
|
57
|
+
|
|
58
|
+
@on('session-changed', { daemon: 'session' })
|
|
59
|
+
changed(e: CustomEvent<Session | null>) {}
|
|
60
|
+
|
|
61
|
+
@respond('confirm-logout', { daemon: 'session' })
|
|
62
|
+
confirm() { return true; }
|
|
63
|
+
```
|
|
64
|
+
|
|
65
|
+
Daemon methods without `{ daemon }` use that instance's private target.
|
|
66
|
+
Controllers resolve through their attached host.
|
|
67
|
+
|
|
68
|
+
Resolution: participant -> nearest provided app context ->
|
|
69
|
+
`context.daemons[name]` -> instance target. No globals, implicit construction,
|
|
70
|
+
fallback, scanning, or late binding.
|
|
71
|
+
|
|
72
|
+
Rules:
|
|
73
|
+
- Provide before element connect/controller attach (`@on`/`@respond` bind then).
|
|
74
|
+
- `@request`/`@dispatch` resolve at invocation.
|
|
75
|
+
- `daemon` and `scope` are mutually exclusive.
|
|
76
|
+
- No selector delegation on daemon targets.
|
|
77
|
+
- Release function is idempotent and makes daemon traffic inert.
|
|
78
|
+
- Multiple instances of the same class and same address under different roots
|
|
79
|
+
are independent.
|
|
80
|
+
- Missing/undecorated/inactive entries fail explicitly.
|
package/docs/ai/decorators.md
CHANGED
|
@@ -4,6 +4,7 @@
|
|
|
4
4
|
- `@element('tag-name', options?)` - Custom element. Options: `{ formAssociated?, renderRoot?: 'shadow'|'light', shadow?: 'open'|'closed'|false, delegatesFocus? }`
|
|
5
5
|
- `@page({ tag, routes, guards?, placard? })` - Routable page
|
|
6
6
|
- `@controller('name')` - Swappable behavior. Required on every controller class. Attach by class (preferred): `controller=${MyController}` in templates, `attachController(el, MyController)`, or `el.controller = MyController`; by string in raw HTML: `controller="name"`
|
|
7
|
+
- `@daemon` - Marks an explicitly constructed app-context daemon. No name argument; context key is address. Never constructs/registers globally.
|
|
7
8
|
- `@layout('tag-name')` - Page wrapper for routing system
|
|
8
9
|
|
|
9
10
|
## Rendering
|
|
@@ -30,8 +31,8 @@
|
|
|
30
31
|
- `@queryAll('selector', { light? })` - NodeList
|
|
31
32
|
|
|
32
33
|
## Events
|
|
33
|
-
- `@on('event', 'selector?', options?)` - Delegation, auto-bound. Options: `{ capture?, once?, passive?, preventDefault?, stopPropagation?, debounce?, throttle?, scope? }`
|
|
34
|
-
- `@dispatch('event-name', options?)` - Emit CustomEvent, detail = return value. Supports async. Options: `{ debounce?, throttle?, dispatchOnUndefined?, scope?, ...EventInit }`
|
|
34
|
+
- `@on('event', 'selector?', options?)` - Delegation, auto-bound. Options: `{ capture?, once?, passive?, preventDefault?, stopPropagation?, debounce?, throttle?, scope?, daemon? }`
|
|
35
|
+
- `@dispatch('event-name', options?)` - Emit CustomEvent, detail = return value. Supports async. Options: `{ debounce?, throttle?, dispatchOnUndefined?, scope?, daemon?, ...EventInit }`
|
|
35
36
|
|
|
36
37
|
### scope (on both `@on` and `@dispatch`)
|
|
37
38
|
|
|
@@ -63,9 +64,10 @@ Unresolved scope → `console.warn`, listener not attached / event not dispatche
|
|
|
63
64
|
Resolver re-runs on reconnect — listeners track DOM moves.
|
|
64
65
|
|
|
65
66
|
## Communication
|
|
66
|
-
- `@request(channel, options?)` - Async generator request pattern
|
|
67
|
-
- `@respond(channel, options?)` - Handle requests from `@request`
|
|
67
|
+
- `@request(channel, options?)` - Async generator request pattern; `{ daemon: 'name' }` targets an app-context daemon
|
|
68
|
+
- `@respond(channel, options?)` - Handle requests from `@request`; `{ daemon: 'name' }` installs on that daemon target
|
|
68
69
|
- `@context(options?)` - Receive router navigation context updates
|
|
70
|
+
- `provideContext(root, context)` / `getContext(participant)` - Explicit raw app-context provisioning and lookup
|
|
69
71
|
|
|
70
72
|
## Observers
|
|
71
73
|
- `@observe(target, selector?, options?)` - Watch intersection, resize, media query, mutation
|
package/docs/ai/events.md
CHANGED
|
@@ -342,6 +342,41 @@ changeColor(color: string) { this.color = color; return { color }; }
|
|
|
342
342
|
confirm() { return { color: this.color }; }
|
|
343
343
|
```
|
|
344
344
|
|
|
345
|
+
## Event bus
|
|
346
|
+
|
|
347
|
+
No bus object, no singleton. Bus = `@dispatch` publishing upward + `@on` subscribing at a chosen ancestor. Scope is a DOM node, so it lives and dies with the DOM.
|
|
348
|
+
|
|
349
|
+
Two publish paths — the choice decides who can hear it:
|
|
350
|
+
- **Bubble from host** — `@dispatch` defaults to `bubbles: true, composed: true`, so it crosses shadow boundaries and passes every ancestor up to `document`. For "this element did something".
|
|
351
|
+
- **Dispatch on a scope** — `@dispatch` takes the same `scope` option as `@on`, firing *on* that target instead of bubbling. For subscribers that are not ancestors (sibling subtree, or a detached host).
|
|
352
|
+
|
|
353
|
+
```typescript
|
|
354
|
+
@dispatch('bus:cart-added') // bubbles from host
|
|
355
|
+
@dispatch('bus:cart-added', { scope: 'global' }) // dispatched on document
|
|
356
|
+
|
|
357
|
+
@on('bus:cart-added', { scope: 'global' }) // document — app-wide
|
|
358
|
+
@on('bus:cart-added', { scope: 'cart-shell' }) // nearest <cart-shell> — per-instance
|
|
359
|
+
```
|
|
360
|
+
|
|
361
|
+
Match the halves: a bubbling publish only reaches subscribers on the host's ancestor chain. Sibling subtree → scope the dispatch too, so both meet on the same node. See [scope on @dispatch](#scope-dispatch-target).
|
|
362
|
+
|
|
363
|
+
Scope choice:
|
|
364
|
+
- `'global'` — genuinely app-wide (auth expiry, theme change, save shortcut)
|
|
365
|
+
- selector string — feature subtree; a second shell elsewhere keeps its own traffic
|
|
366
|
+
- `EventTarget` / resolver — you hold the node, or it moves and must re-resolve
|
|
367
|
+
|
|
368
|
+
Prefer the narrowest scope that works; `'global'` means every instance hears every message.
|
|
369
|
+
|
|
370
|
+
`bus:` is a naming convention, not a framework feature. Teardown is automatic — removed on disconnect from the resolved target, re-resolved on reconnect. Unresolvable selector → listener skipped + `console.warn`, never bound to the wrong node. Full table: [scope](#scope-listener-attachment-target).
|
|
371
|
+
|
|
372
|
+
Need a reply rather than a broadcast → [@request / @respond](./request-response.md).
|
|
373
|
+
|
|
374
|
+
For stateful objects explicitly supplied by an application context, use
|
|
375
|
+
`{ daemon: 'name' }`. Both halves must target the same daemon address; daemon
|
|
376
|
+
methods themselves default to their own private target. See
|
|
377
|
+
[daemons](./daemons.md). Daemon targets are not DOM scopes: `scope` and
|
|
378
|
+
`daemon` cannot be combined, and selector delegation is unavailable.
|
|
379
|
+
|
|
345
380
|
## Custom events
|
|
346
381
|
|
|
347
382
|
Dispatching manually:
|
package/docs/ai/patterns.md
CHANGED
|
@@ -94,6 +94,50 @@ Enabled automatically when Snice loads — no setup needed.
|
|
|
94
94
|
// <table controller="table-loader"></table>
|
|
95
95
|
```
|
|
96
96
|
|
|
97
|
+
## Daemon
|
|
98
|
+
|
|
99
|
+
Ordinary state/lifecycle object owned by the application. Construction and
|
|
100
|
+
teardown stay explicit; consumers use a context address instead of importing
|
|
101
|
+
the implementation class.
|
|
102
|
+
|
|
103
|
+
```typescript
|
|
104
|
+
@daemon
|
|
105
|
+
class SessionDaemon {
|
|
106
|
+
session: Session | null = null;
|
|
107
|
+
|
|
108
|
+
@respond('session/get')
|
|
109
|
+
getSession() { return this.session; }
|
|
110
|
+
|
|
111
|
+
@on('session/set')
|
|
112
|
+
setSession(event: CustomEvent<Session>) {
|
|
113
|
+
this.session = event.detail;
|
|
114
|
+
this.changed();
|
|
115
|
+
}
|
|
116
|
+
|
|
117
|
+
@dispatch('session/changed')
|
|
118
|
+
changed() { return this.session; }
|
|
119
|
+
}
|
|
120
|
+
|
|
121
|
+
const session = new SessionDaemon();
|
|
122
|
+
const release = provideContext(appRoot, { daemons: { session } });
|
|
123
|
+
|
|
124
|
+
@request('session/get', { daemon: 'session' })
|
|
125
|
+
async *getSession(): Response<Session | null> { return yield {}; }
|
|
126
|
+
|
|
127
|
+
@dispatch('session/set', { daemon: 'session' })
|
|
128
|
+
setSession(session: Session) { return session; }
|
|
129
|
+
|
|
130
|
+
@on('session/changed', { daemon: 'session' })
|
|
131
|
+
sessionChanged(event: CustomEvent<Session | null>) {}
|
|
132
|
+
```
|
|
133
|
+
|
|
134
|
+
- Provide before element connection/controller attachment.
|
|
135
|
+
- Router `context.daemons` uses the same provider automatically.
|
|
136
|
+
- `@request`/`@respond` = one reply; `@dispatch`/`@on` = notifications.
|
|
137
|
+
- `daemon` cannot be combined with DOM `scope`; daemon listeners cannot delegate selectors.
|
|
138
|
+
- Call `release()` during app/test teardown.
|
|
139
|
+
- See `docs/ai/daemons.md`.
|
|
140
|
+
|
|
97
141
|
## Page + Router
|
|
98
142
|
|
|
99
143
|
**Module Structure (avoids circular imports):**
|
|
@@ -185,7 +229,7 @@ class API {
|
|
|
185
229
|
@element('user-profile')
|
|
186
230
|
class UserProfile extends HTMLElement {
|
|
187
231
|
@request('fetch-user')
|
|
188
|
-
async *fetchUser(id: string):
|
|
232
|
+
async *fetchUser(id: string): Response<User> {
|
|
189
233
|
const user = await (yield { id }); // yield = send request, await = get response
|
|
190
234
|
return user;
|
|
191
235
|
}
|
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
|
|
3
3
|
Mirrors `docs/request-response.md`.
|
|
4
4
|
|
|
5
|
-
Request/response communication between elements and
|
|
5
|
+
Request/response communication between elements, controllers, and provided daemons using async generators.
|
|
6
6
|
|
|
7
7
|
## Why
|
|
8
8
|
|
|
@@ -27,6 +27,7 @@ function request(requestName: string, options?: RequestOptions): MethodDecorator
|
|
|
27
27
|
function respond(requestName: string, options?: RespondOptions): MethodDecorator
|
|
28
28
|
|
|
29
29
|
interface RequestOptions extends EventInit {
|
|
30
|
+
daemon?: string; // named daemon from nearest provided app context
|
|
30
31
|
timeout?: number; // response timeout ms, default 120000 (2 min)
|
|
31
32
|
discoveryTimeout?: number; // handler discovery timeout ms, default 50
|
|
32
33
|
debounce?: number;
|
|
@@ -36,14 +37,20 @@ interface RequestOptions extends EventInit {
|
|
|
36
37
|
}
|
|
37
38
|
|
|
38
39
|
interface RespondOptions {
|
|
40
|
+
daemon?: string; // install responder on named daemon target
|
|
39
41
|
debounce?: number;
|
|
40
42
|
throttle?: number;
|
|
41
43
|
}
|
|
42
44
|
|
|
43
|
-
//
|
|
44
|
-
type
|
|
45
|
+
// Public return type for methods decorated with @request:
|
|
46
|
+
type Response<T = any> = T | any;
|
|
45
47
|
```
|
|
46
48
|
|
|
49
|
+
TypeScript cannot model a method decorator changing an async generator into a
|
|
50
|
+
promise-returning method. This is a deliberate pragmatic annotation: it keeps
|
|
51
|
+
strict consumers usable and documents `T`; the decorated runtime method
|
|
52
|
+
returns a promise for `T`.
|
|
53
|
+
|
|
47
54
|
### Response debounce/throttle
|
|
48
55
|
|
|
49
56
|
```typescript
|
|
@@ -65,6 +72,16 @@ class ProcessingController implements IController {
|
|
|
65
72
|
}
|
|
66
73
|
```
|
|
67
74
|
|
|
75
|
+
Daemon communication uses the same protocol without DOM bubbling:
|
|
76
|
+
|
|
77
|
+
```typescript
|
|
78
|
+
@request('get-session', { daemon: 'session' })
|
|
79
|
+
async *getSession() { return yield {}; }
|
|
80
|
+
```
|
|
81
|
+
|
|
82
|
+
The daemon's plain `@respond('get-session')` handles it. See
|
|
83
|
+
[daemons](./daemons.md).
|
|
84
|
+
|
|
68
85
|
## Element-Side Requests
|
|
69
86
|
|
|
70
87
|
```typescript
|
|
@@ -75,7 +92,7 @@ class ProductCard extends HTMLElement {
|
|
|
75
92
|
@property() price = '';
|
|
76
93
|
|
|
77
94
|
@request('fetch-product')
|
|
78
|
-
async *loadProduct():
|
|
95
|
+
async *loadProduct(): Response<void> {
|
|
79
96
|
const product = await (yield { id: this.productId });
|
|
80
97
|
this.name = product.name;
|
|
81
98
|
this.price = product.price;
|
|
@@ -121,17 +138,17 @@ Elements never call `fetch()` or manage data directly — they yield requests up
|
|
|
121
138
|
|
|
122
139
|
```typescript
|
|
123
140
|
@request('heavy-computation', { discoveryTimeout: 50, timeout: 30000 })
|
|
124
|
-
async *compute():
|
|
141
|
+
async *compute(): Response<any> { return await (yield data); }
|
|
125
142
|
```
|
|
126
143
|
|
|
127
144
|
### Debounce/Throttle
|
|
128
145
|
|
|
129
146
|
```typescript
|
|
130
147
|
@request('search', { debounce: 300 })
|
|
131
|
-
async *search():
|
|
148
|
+
async *search(): Response<any[]> { return await (yield { query: this.searchTerm }); }
|
|
132
149
|
|
|
133
150
|
@request('track', { throttle: 1000 })
|
|
134
|
-
async *trackEvent():
|
|
151
|
+
async *trackEvent(): Response<void> { await (yield { event: 'scroll', position: window.scrollY }); }
|
|
135
152
|
```
|
|
136
153
|
|
|
137
154
|
## Error Handling
|
|
@@ -140,7 +157,7 @@ async *trackEvent(): RequestResult<void> { await (yield { event: 'scroll', posit
|
|
|
140
157
|
|
|
141
158
|
```typescript
|
|
142
159
|
@request('load-data', { timeout: 5000 })
|
|
143
|
-
async *loadData():
|
|
160
|
+
async *loadData(): Response<void> {
|
|
144
161
|
try {
|
|
145
162
|
this.data = await (yield { id: this.dataId });
|
|
146
163
|
this.error = '';
|
|
@@ -201,7 +218,7 @@ class LiveTicker extends HTMLElement {
|
|
|
201
218
|
@property() symbol = 'BTC';
|
|
202
219
|
|
|
203
220
|
@request('subscribe-ticker')
|
|
204
|
-
async *subscribe():
|
|
221
|
+
async *subscribe(): Response<void> { await (yield { symbol: this.symbol }); }
|
|
205
222
|
|
|
206
223
|
@on('ticker-update')
|
|
207
224
|
onUpdate(e: CustomEvent) { this.price = e.detail.price; }
|
package/docs/ai/routing.md
CHANGED
|
@@ -25,7 +25,7 @@ interface RouterOptions {
|
|
|
25
25
|
document?: Document; // override document object (testing)
|
|
26
26
|
transition?: Transition; // global transition config
|
|
27
27
|
layout?: string; // default layout tag for all pages
|
|
28
|
-
context?: any; //
|
|
28
|
+
context?: any; // app context; may expose daemons
|
|
29
29
|
fetcher?: Fetcher; // optional fetch middleware — see docs/ai/fetcher.md
|
|
30
30
|
}
|
|
31
31
|
```
|
|
@@ -45,6 +45,19 @@ class AppContext {
|
|
|
45
45
|
const { page, initialize } = Router({ target: '#app', type: 'hash', context: new AppContext() });
|
|
46
46
|
```
|
|
47
47
|
|
|
48
|
+
Router also provides the raw app context beneath `target`, using the same
|
|
49
|
+
`provideContext()` mechanism available to non-router applications. Explicitly
|
|
50
|
+
constructed `@daemon` instances may be addressed through `context.daemons`:
|
|
51
|
+
|
|
52
|
+
```typescript
|
|
53
|
+
const session = new SessionDaemon();
|
|
54
|
+
Router({
|
|
55
|
+
target: '#app',
|
|
56
|
+
type: 'hash',
|
|
57
|
+
context: { daemons: { session } }
|
|
58
|
+
});
|
|
59
|
+
```
|
|
60
|
+
|
|
48
61
|
### Module structure (avoids circular imports)
|
|
49
62
|
|
|
50
63
|
```typescript
|
|
@@ -176,4 +189,6 @@ function Router(options: RouterOptions): {
|
|
|
176
189
|
|
|
177
190
|
- `navigate(path: string): Promise<void>` — navigates to `path`; uses hash or pushstate depending on router `type`.
|
|
178
191
|
- `initialize(): void` — starts listening for route changes; must be called after all pages are defined.
|
|
192
|
+
- Do not add `@element` to an `@page` class. The Router-returned page decorator
|
|
193
|
+
already registers the custom element and applies Snice element behavior.
|
|
179
194
|
- `register(route: string, tag: string, transition?: Transition, guards?: Guard | Guard[], layout?: string | false, placard?: Placard | ((ctx: AppContext) => Placard)): void` — manually registers a route without the `@page` decorator. Note: the return-type shape above lists `register` with 4 params; this fuller 6-param signature (adding `layout`, `placard`) is documented separately in the source.
|
package/docs/cli.md
CHANGED
|
@@ -50,6 +50,13 @@ npx snice validate # source analyzer only
|
|
|
50
50
|
|
|
51
51
|
- an `@element`-decorated class that does not extend `HTMLElement` (or a Snice element subclass) — Snice registers and renders only element subclasses
|
|
52
52
|
- deep imports that were never released package paths, such as `snice/decorators`
|
|
53
|
+
- a Router without `target`, `type`, or a project-wide `initialize()` call
|
|
54
|
+
- a routed class combining `@page` with redundant `@element`
|
|
55
|
+
|
|
56
|
+
It also gives non-blocking architecture suggestions: keep `@page`, `@element`,
|
|
57
|
+
`@controller`, and `@daemon` classes under `src/pages`, `src/components`,
|
|
58
|
+
`src/controllers`, and `src/daemons`; extract clearly service-heavy or repeated
|
|
59
|
+
page logic into a controller. Small route orchestration remains valid page code.
|
|
53
60
|
|
|
54
61
|
Both accept `--json` for CI.
|
|
55
62
|
|
|
@@ -32,9 +32,10 @@ Individual breadcrumb item (data element, no shadow DOM).
|
|
|
32
32
|
| Property | Attribute | Type | Default | Description |
|
|
33
33
|
|----------|-----------|------|---------|-------------|
|
|
34
34
|
| `items` | -- | `BreadcrumbItem[]` | `[]` | Array of breadcrumb items (JS property only) |
|
|
35
|
-
| `separator` | `separator` | `'/' \| '>' \| '
|
|
35
|
+
| `separator` | `separator` | `'/' \| '>' \| '»' \| '•' \| '\|'` | `'/'` | Separator between items |
|
|
36
36
|
| `size` | `size` | `'small' \| 'medium' \| 'large'` | `'medium'` | Breadcrumb size |
|
|
37
37
|
| `maxItems` | `max-items` | `number` | `0` | Max items to show (0 = show all). Collapsed items show an ellipsis. |
|
|
38
|
+
| `collapsed` | `collapsed` | `boolean` | `true` | Whether the trail is collapsed behind the ellipsis. Clicking the ellipsis sets it `false`; it resets to `true` when `items`, `separator`, or `maxItems` change. Only has an effect once `maxItems` is exceeded. |
|
|
38
39
|
|
|
39
40
|
### BreadcrumbItem Interface
|
|
40
41
|
|
|
@@ -23,7 +23,7 @@ Display and select dates with event support, date restrictions, and locale-aware
|
|
|
23
23
|
| `events` | `CalendarEvent[]` | `[]` | Calendar events |
|
|
24
24
|
| `minDate` (attr: `min-date`) | `Date \| string` | `''` | Minimum selectable date |
|
|
25
25
|
| `maxDate` (attr: `max-date`) | `Date \| string` | `''` | Maximum selectable date |
|
|
26
|
-
| `disabledDates`
|
|
26
|
+
| `disabledDates` | `(Date \| string)[]` | `[]` | Disabled dates (JS-only; no attribute) |
|
|
27
27
|
| `highlightToday` (attr: `highlight-today`) | `boolean` | `true` | Highlight today's date |
|
|
28
28
|
| `showWeekNumbers` (attr: `show-week-numbers`) | `boolean` | `false` | Show week numbers |
|
|
29
29
|
| `firstDayOfWeek` (attr: `first-day-of-week`) | `number` | `0` | First day of week (0=Sun, 1=Mon) |
|
|
@@ -19,7 +19,7 @@ Live camera feed with built-in mobile-style controls, flexible positioning, aspe
|
|
|
19
19
|
|
|
20
20
|
| Property | Type | Default | Description |
|
|
21
21
|
|----------|------|---------|-------------|
|
|
22
|
-
| `autoStart` (attr: `auto-start`) | `boolean` | `
|
|
22
|
+
| `autoStart` (attr: `auto-start`) | `boolean` | `false` | Auto-start camera on load |
|
|
23
23
|
| `facingMode` (attr: `facing-mode`) | `'user' \| 'environment'` | `'user'` | Front or back camera |
|
|
24
24
|
| `mirror` | `boolean` | `true` | Mirror video for front camera |
|
|
25
25
|
| `controlsPosition` (attr: `controls-position`) | `ControlsPosition` | `'auto'` | Control button positioning |
|
package/docs/components/chart.md
CHANGED
|
@@ -19,7 +19,7 @@ General-purpose charting component supporting 10 chart types with animations, in
|
|
|
19
19
|
| `type` | `ChartType` | `'line'` | Chart type: `'line'`, `'bar'`, `'horizontal-bar'`, `'area'`, `'pie'`, `'donut'`, `'scatter'`, `'bubble'`, `'radar'`, `'mixed'` |
|
|
20
20
|
| `datasets` | `ChartDataset[]` | `[]` | Chart datasets (property only) |
|
|
21
21
|
| `labels` | `string[]` | `[]` | X-axis labels (property only) |
|
|
22
|
-
| `options` | `ChartOptions` |
|
|
22
|
+
| `options` | `ChartOptions` | see description | Chart options (property only). Defaults: responsive, no fixed aspect ratio, clickable legend on top, hover tooltip, 500ms ease-out animation, x/y grids on |
|
|
23
23
|
| `width` | `number` | `0` | Chart width (0 = auto) |
|
|
24
24
|
| `height` | `number` | `0` | Chart height (0 = auto) |
|
|
25
25
|
|
|
@@ -13,6 +13,10 @@ Display code with syntax highlighting, line numbers, and copy functionality. Use
|
|
|
13
13
|
- [Basic Usage](#basic-usage)
|
|
14
14
|
- [Examples](#examples)
|
|
15
15
|
- [Accessibility](#accessibility)
|
|
16
|
+
- [Fetch Mode](#fetch-mode)
|
|
17
|
+
- [Grammar System](#grammar-system)
|
|
18
|
+
- [Highlighter API](#highlighter-api)
|
|
19
|
+
- [Token CSS Classes](#token-css-classes)
|
|
16
20
|
|
|
17
21
|
## Properties
|
|
18
22
|
|
|
@@ -20,10 +24,10 @@ Display code with syntax highlighting, line numbers, and copy functionality. Use
|
|
|
20
24
|
|----------|------|---------|-------------|
|
|
21
25
|
| `code` | `string` | `''` | Code content (set via slot or property) |
|
|
22
26
|
| `language` | `CodeLanguage` | `'plaintext'` | Programming language |
|
|
23
|
-
| `grammar` | `Grammar \| string \| null` | `
|
|
27
|
+
| `grammar` | `Grammar \| string \| null` | `''` | Grammar object or URL to grammar JSON |
|
|
24
28
|
| `showLineNumbers` (attr: `show-line-numbers`) | `boolean` | `false` | Show line numbers |
|
|
25
29
|
| `startLine` (attr: `start-line`) | `number` | `1` | Starting line number |
|
|
26
|
-
| `highlightLines`
|
|
30
|
+
| `highlightLines` | `number[]` | `[]` | Lines to highlight (JS-only; no attribute) |
|
|
27
31
|
| `copyable` | `boolean` | `true` | Show copy button |
|
|
28
32
|
| `filename` | `string` | `''` | File name to display in header |
|
|
29
33
|
| `format` | `string` | `''` | Formatter name from grammar (e.g. `"pretty"`), or any truthy string with `setFormatter()` |
|
|
@@ -104,10 +108,11 @@ console.log(greeting);
|
|
|
104
108
|
|
|
105
109
|
### Highlight Specific Lines
|
|
106
110
|
|
|
107
|
-
|
|
111
|
+
Set `highlightLines` in JavaScript to draw attention to specific lines. There is no
|
|
112
|
+
`highlight-lines` attribute -- the property is JS-only.
|
|
108
113
|
|
|
109
114
|
```html
|
|
110
|
-
<snice-code-block grammar="grammars/python.json" language="python"
|
|
115
|
+
<snice-code-block id="snippet" grammar="grammars/python.json" language="python">
|
|
111
116
|
def hello():
|
|
112
117
|
name = "World"
|
|
113
118
|
greeting = f"Hello {name}"
|
|
@@ -115,6 +120,10 @@ def hello():
|
|
|
115
120
|
</snice-code-block>
|
|
116
121
|
```
|
|
117
122
|
|
|
123
|
+
```typescript
|
|
124
|
+
document.getElementById('snippet').highlightLines = [2, 3, 4];
|
|
125
|
+
```
|
|
126
|
+
|
|
118
127
|
### Programmatic Code
|
|
119
128
|
|
|
120
129
|
Set code via the `code` property for dynamic content.
|