snice 4.8.0 → 4.9.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/camera-annotate.d.ts +27 -0
- package/adapters/react/camera-annotate.d.ts.map +1 -0
- package/adapters/react/camera-annotate.js +24 -0
- package/adapters/react/camera-annotate.js.map +1 -0
- package/adapters/react/camera-annotate.tsx +35 -0
- package/adapters/react/candlestick.d.ts +34 -0
- package/adapters/react/candlestick.d.ts.map +1 -0
- package/adapters/react/candlestick.js +24 -0
- package/adapters/react/candlestick.js.map +1 -0
- package/adapters/react/candlestick.tsx +42 -0
- package/adapters/react/components.d.ts +14 -0
- package/adapters/react/components.d.ts.map +1 -1
- package/adapters/react/components.js +7 -0
- package/adapters/react/components.js.map +1 -1
- package/adapters/react/components.ts +14 -0
- package/adapters/react/funnel.d.ts +31 -0
- package/adapters/react/funnel.d.ts.map +1 -0
- package/adapters/react/funnel.js +24 -0
- package/adapters/react/funnel.js.map +1 -0
- package/adapters/react/funnel.tsx +39 -0
- package/adapters/react/network-graph.d.ts +32 -0
- package/adapters/react/network-graph.d.ts.map +1 -0
- package/adapters/react/network-graph.js +24 -0
- package/adapters/react/network-graph.js.map +1 -0
- package/adapters/react/network-graph.tsx +40 -0
- package/adapters/react/sankey.d.ts +31 -0
- package/adapters/react/sankey.d.ts.map +1 -0
- package/adapters/react/sankey.js +24 -0
- package/adapters/react/sankey.js.map +1 -0
- package/adapters/react/sankey.tsx +39 -0
- package/adapters/react/time-range-picker.d.ts +33 -0
- package/adapters/react/time-range-picker.d.ts.map +1 -0
- package/adapters/react/time-range-picker.js +24 -0
- package/adapters/react/time-range-picker.js.map +1 -0
- package/adapters/react/time-range-picker.tsx +41 -0
- package/adapters/react/treemap.d.ts +30 -0
- package/adapters/react/treemap.d.ts.map +1 -0
- package/adapters/react/treemap.js +24 -0
- package/adapters/react/treemap.js.map +1 -0
- package/adapters/react/treemap.tsx +38 -0
- package/adapters/react/virtual-scroller.d.ts +1 -0
- package/adapters/react/virtual-scroller.d.ts.map +1 -1
- package/adapters/react/virtual-scroller.js +1 -1
- package/adapters/react/virtual-scroller.js.map +1 -1
- package/adapters/react/virtual-scroller.tsx +2 -1
- 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/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/breadcrumbs/snice-breadcrumbs.js +2 -2
- package/dist/cdn/breadcrumbs/snice-breadcrumbs.js.map +1 -1
- package/dist/cdn/breadcrumbs/snice-breadcrumbs.min.js +13 -13
- package/dist/cdn/breadcrumbs/snice-breadcrumbs.min.js.map +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/snice-camera.js +1 -1
- package/dist/cdn/camera/snice-camera.min.js +1 -1
- package/dist/cdn/camera-annotate/README.md +27 -0
- package/dist/cdn/camera-annotate/snice-camera-annotate.js +730 -0
- package/dist/cdn/camera-annotate/snice-camera-annotate.js.map +1 -0
- package/dist/cdn/camera-annotate/snice-camera-annotate.min.js +144 -0
- package/dist/cdn/camera-annotate/snice-camera-annotate.min.js.map +1 -0
- package/dist/cdn/candlestick/README.md +27 -0
- package/dist/cdn/candlestick/snice-candlestick.js +717 -0
- package/dist/cdn/candlestick/snice-candlestick.js.map +1 -0
- package/dist/cdn/candlestick/snice-candlestick.min.js +22 -0
- package/dist/cdn/candlestick/snice-candlestick.min.js.map +1 -0
- package/dist/cdn/card/snice-card.js +1 -1
- package/dist/cdn/card/snice-card.min.js +1 -1
- package/dist/cdn/carousel/snice-carousel.js +1 -1
- package/dist/cdn/carousel/snice-carousel.min.js +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/date-picker/snice-date-picker.js +1 -1
- package/dist/cdn/date-picker/snice-date-picker.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/funnel/README.md +27 -0
- package/dist/cdn/funnel/snice-funnel.js +424 -0
- package/dist/cdn/funnel/snice-funnel.js.map +1 -0
- package/dist/cdn/funnel/snice-funnel.min.js +20 -0
- package/dist/cdn/funnel/snice-funnel.min.js.map +1 -0
- 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/README.md +2 -2
- package/dist/cdn/layout/snice-layout.js +23 -6
- package/dist/cdn/layout/snice-layout.js.map +1 -1
- package/dist/cdn/layout/snice-layout.min.js +2 -2
- package/dist/cdn/layout/snice-layout.min.js.map +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/README.md +6 -2
- package/dist/cdn/list/snice-list.js +87 -10
- package/dist/cdn/list/snice-list.js.map +1 -1
- package/dist/cdn/list/snice-list.min.js +20 -6
- package/dist/cdn/list/snice-list.min.js.map +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/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/README.md +2 -2
- package/dist/cdn/nav/snice-nav.js +23 -6
- package/dist/cdn/nav/snice-nav.js.map +1 -1
- package/dist/cdn/nav/snice-nav.min.js +2 -2
- package/dist/cdn/nav/snice-nav.min.js.map +1 -1
- package/dist/cdn/network-graph/README.md +27 -0
- package/dist/cdn/network-graph/snice-network-graph.js +788 -0
- package/dist/cdn/network-graph/snice-network-graph.js.map +1 -0
- package/dist/cdn/network-graph/snice-network-graph.min.js +13 -0
- package/dist/cdn/network-graph/snice-network-graph.min.js.map +1 -0
- package/dist/cdn/pagination/README.md +2 -2
- package/dist/cdn/pagination/snice-pagination.js +13 -13
- package/dist/cdn/pagination/snice-pagination.js.map +1 -1
- package/dist/cdn/pagination/snice-pagination.min.js +14 -14
- package/dist/cdn/pagination/snice-pagination.min.js.map +1 -1
- package/dist/cdn/paint/snice-paint.js +1 -1
- package/dist/cdn/paint/snice-paint.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/runtime/snice-runtime.esm.js +3 -3
- package/dist/cdn/runtime/snice-runtime.esm.js.map +1 -1
- package/dist/cdn/runtime/snice-runtime.esm.min.js +3 -3
- package/dist/cdn/runtime/snice-runtime.esm.min.js.map +1 -1
- package/dist/cdn/runtime/snice-runtime.js +3 -3
- package/dist/cdn/runtime/snice-runtime.js.map +1 -1
- package/dist/cdn/runtime/snice-runtime.min.js +3 -3
- package/dist/cdn/runtime/snice-runtime.min.js.map +1 -1
- package/dist/cdn/sankey/README.md +27 -0
- package/dist/cdn/sankey/snice-sankey.js +679 -0
- package/dist/cdn/sankey/snice-sankey.js.map +1 -0
- package/dist/cdn/sankey/snice-sankey.min.js +21 -0
- package/dist/cdn/sankey/snice-sankey.min.js.map +1 -0
- 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/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/stepper/README.md +6 -2
- package/dist/cdn/stepper/snice-stepper.js +77 -10
- package/dist/cdn/stepper/snice-stepper.js.map +1 -1
- package/dist/cdn/stepper/snice-stepper.min.js +13 -9
- package/dist/cdn/stepper/snice-stepper.min.js.map +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/terminal/snice-terminal.js +1 -1
- package/dist/cdn/terminal/snice-terminal.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/README.md +27 -0
- package/dist/cdn/time-range-picker/snice-time-range-picker.js +635 -0
- package/dist/cdn/time-range-picker/snice-time-range-picker.js.map +1 -0
- package/dist/cdn/time-range-picker/snice-time-range-picker.min.js +34 -0
- package/dist/cdn/time-range-picker/snice-time-range-picker.min.js.map +1 -0
- 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/README.md +5 -1
- package/dist/cdn/tree/snice-tree.js +4 -8
- package/dist/cdn/tree/snice-tree.js.map +1 -1
- package/dist/cdn/tree/snice-tree.min.js +5 -5
- package/dist/cdn/tree/snice-tree.min.js.map +1 -1
- package/dist/cdn/treemap/README.md +27 -0
- package/dist/cdn/treemap/snice-treemap.js +522 -0
- package/dist/cdn/treemap/snice-treemap.js.map +1 -0
- package/dist/cdn/treemap/snice-treemap.min.js +14 -0
- package/dist/cdn/treemap/snice-treemap.min.js.map +1 -0
- package/dist/cdn/virtual-scroller/README.md +2 -2
- package/dist/cdn/virtual-scroller/snice-virtual-scroller.js +47 -16
- package/dist/cdn/virtual-scroller/snice-virtual-scroller.js.map +1 -1
- package/dist/cdn/virtual-scroller/snice-virtual-scroller.min.js +9 -9
- package/dist/cdn/virtual-scroller/snice-virtual-scroller.min.js.map +1 -1
- package/dist/components/breadcrumbs/snice-breadcrumbs.js +1 -1
- package/dist/components/breadcrumbs/snice-breadcrumbs.js.map +1 -1
- package/dist/components/camera-annotate/snice-camera-annotate.d.ts +68 -0
- package/dist/components/camera-annotate/snice-camera-annotate.js +663 -0
- package/dist/components/camera-annotate/snice-camera-annotate.js.map +1 -0
- package/dist/components/camera-annotate/snice-camera-annotate.types.d.ts +50 -0
- package/dist/components/candlestick/snice-candlestick.d.ts +78 -0
- package/dist/components/candlestick/snice-candlestick.js +650 -0
- package/dist/components/candlestick/snice-candlestick.js.map +1 -0
- package/dist/components/candlestick/snice-candlestick.types.d.ts +40 -0
- package/dist/components/funnel/snice-funnel.d.ts +37 -0
- package/dist/components/funnel/snice-funnel.js +357 -0
- package/dist/components/funnel/snice-funnel.js.map +1 -0
- package/dist/components/funnel/snice-funnel.types.d.ts +28 -0
- package/dist/components/list/snice-list-item.d.ts +2 -0
- package/dist/components/list/snice-list-item.js +20 -2
- package/dist/components/list/snice-list-item.js.map +1 -1
- package/dist/components/nav/snice-nav.js +22 -5
- package/dist/components/nav/snice-nav.js.map +1 -1
- package/dist/components/network-graph/snice-network-graph.d.ts +80 -0
- package/dist/components/network-graph/snice-network-graph.js +721 -0
- package/dist/components/network-graph/snice-network-graph.js.map +1 -0
- package/dist/components/network-graph/snice-network-graph.types.d.ts +49 -0
- package/dist/components/pagination/snice-pagination.js +12 -12
- package/dist/components/sankey/snice-sankey.d.ts +46 -0
- package/dist/components/sankey/snice-sankey.js +612 -0
- package/dist/components/sankey/snice-sankey.js.map +1 -0
- package/dist/components/sankey/snice-sankey.types.d.ts +59 -0
- package/dist/components/stepper/snice-stepper.js +9 -3
- package/dist/components/stepper/snice-stepper.js.map +1 -1
- package/dist/components/time-range-picker/snice-time-range-picker.d.ts +67 -0
- package/dist/components/time-range-picker/snice-time-range-picker.js +568 -0
- package/dist/components/time-range-picker/snice-time-range-picker.js.map +1 -0
- package/dist/components/time-range-picker/snice-time-range-picker.types.d.ts +39 -0
- package/dist/components/treemap/snice-treemap.d.ts +49 -0
- package/dist/components/treemap/snice-treemap.js +455 -0
- package/dist/components/treemap/snice-treemap.js.map +1 -0
- package/dist/components/treemap/snice-treemap.types.d.ts +42 -0
- package/dist/components/virtual-scroller/snice-virtual-scroller.d.ts +5 -0
- package/dist/components/virtual-scroller/snice-virtual-scroller.js +47 -16
- package/dist/components/virtual-scroller/snice-virtual-scroller.js.map +1 -1
- package/dist/index.cjs +1 -1
- package/dist/index.cjs.map +1 -1
- package/dist/index.esm.js +1 -1
- package/dist/index.esm.js.map +1 -1
- package/dist/index.iife.js +1 -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/components/camera-annotate.md +82 -0
- package/docs/ai/components/candlestick.md +79 -0
- package/docs/ai/components/funnel.md +86 -0
- package/docs/ai/components/network-graph.md +87 -0
- package/docs/ai/components/sankey.md +63 -0
- package/docs/ai/components/time-range-picker.md +78 -0
- package/docs/ai/components/treemap.md +78 -0
- package/docs/components/camera-annotate.md +186 -0
- package/docs/components/candlestick.md +196 -0
- package/docs/components/funnel.md +191 -0
- package/docs/components/network-graph.md +215 -0
- package/docs/components/sankey.md +201 -0
- package/docs/components/time-range-picker.md +213 -0
- package/docs/components/treemap.md +198 -0
- package/package.json +1 -1
package/dist/symbols.cjs
CHANGED
package/dist/symbols.esm.js
CHANGED
package/dist/transitions.cjs
CHANGED
package/dist/transitions.esm.js
CHANGED
|
@@ -0,0 +1,82 @@
|
|
|
1
|
+
# snice-camera-annotate
|
|
2
|
+
|
|
3
|
+
Image annotation component combining camera capture + freehand drawing + labeled annotations.
|
|
4
|
+
|
|
5
|
+
## Properties
|
|
6
|
+
|
|
7
|
+
```typescript
|
|
8
|
+
mode: 'camera' | 'annotate' = 'camera';
|
|
9
|
+
autoRotateColors: boolean = true; // attribute: auto-rotate-colors
|
|
10
|
+
showLabelsPanel: boolean = true; // attribute: show-labels-panel
|
|
11
|
+
```
|
|
12
|
+
|
|
13
|
+
## Methods
|
|
14
|
+
|
|
15
|
+
```typescript
|
|
16
|
+
capture(): Promise<void>;
|
|
17
|
+
exportImage(options?: { includeLabels?: boolean }): string;
|
|
18
|
+
exportAnnotations(): AnnotationData;
|
|
19
|
+
importAnnotations(data: AnnotationData): void;
|
|
20
|
+
clearAnnotations(): void;
|
|
21
|
+
```
|
|
22
|
+
|
|
23
|
+
## Events
|
|
24
|
+
|
|
25
|
+
```typescript
|
|
26
|
+
'@snice/capture' → { dataURL: string; width: number; height: number }
|
|
27
|
+
'@snice/annotate' → { annotation: Annotation }
|
|
28
|
+
'@snice/annotation-change' → { annotations: Annotation[] }
|
|
29
|
+
```
|
|
30
|
+
|
|
31
|
+
## Types
|
|
32
|
+
|
|
33
|
+
```typescript
|
|
34
|
+
interface Annotation {
|
|
35
|
+
id: string;
|
|
36
|
+
strokeId: string;
|
|
37
|
+
label: string;
|
|
38
|
+
color: string;
|
|
39
|
+
visible: boolean;
|
|
40
|
+
timestamp: number;
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
interface AnnotationData {
|
|
44
|
+
annotations: Annotation[];
|
|
45
|
+
strokes: AnnotationStroke[];
|
|
46
|
+
imageWidth: number;
|
|
47
|
+
imageHeight: number;
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
interface AnnotationStroke {
|
|
51
|
+
id: string;
|
|
52
|
+
color: string;
|
|
53
|
+
width: number;
|
|
54
|
+
points: { x: number; y: number }[];
|
|
55
|
+
timestamp: number;
|
|
56
|
+
}
|
|
57
|
+
```
|
|
58
|
+
|
|
59
|
+
## Usage
|
|
60
|
+
|
|
61
|
+
```html
|
|
62
|
+
<!-- Default -->
|
|
63
|
+
<snice-camera-annotate></snice-camera-annotate>
|
|
64
|
+
|
|
65
|
+
<!-- No sidebar -->
|
|
66
|
+
<snice-camera-annotate show-labels-panel="false"></snice-camera-annotate>
|
|
67
|
+
|
|
68
|
+
<!-- Manual color selection -->
|
|
69
|
+
<snice-camera-annotate auto-rotate-colors="false"></snice-camera-annotate>
|
|
70
|
+
```
|
|
71
|
+
|
|
72
|
+
## Features
|
|
73
|
+
|
|
74
|
+
- Camera capture → freehand draw → label workflow
|
|
75
|
+
- 12-color preset palette with auto-rotation
|
|
76
|
+
- Sidebar labels linked to drawn shapes
|
|
77
|
+
- Hover label highlights shape, dims others (opacity 0.2 + grayscale)
|
|
78
|
+
- Show/hide individual and bulk annotations
|
|
79
|
+
- Export image with/without rendered labels
|
|
80
|
+
- Save/load annotation data (JSON)
|
|
81
|
+
- Undo last stroke
|
|
82
|
+
- Adjustable stroke width
|
|
@@ -0,0 +1,79 @@
|
|
|
1
|
+
# snice-candlestick
|
|
2
|
+
|
|
3
|
+
SVG-based OHLC candlestick chart for financial data visualization.
|
|
4
|
+
|
|
5
|
+
## Properties
|
|
6
|
+
|
|
7
|
+
```typescript
|
|
8
|
+
data: CandleData[] = []; // {date, open, high, low, close, volume?}
|
|
9
|
+
showVolume: boolean = false; // Show volume bars below chart
|
|
10
|
+
showGrid: boolean = true; // Show horizontal grid lines
|
|
11
|
+
showCrosshair: boolean = true; // Show crosshair on hover
|
|
12
|
+
bullishColor: string = ''; // Custom bullish (close >= open) color
|
|
13
|
+
bearishColor: string = ''; // Custom bearish (close < open) color
|
|
14
|
+
timeFormat: 'auto'|'date'|'time'|'datetime'|'month'|'year' = 'auto';
|
|
15
|
+
yAxisFormat: 'number'|'currency'|'percent' = 'number';
|
|
16
|
+
zoomEnabled: boolean = true; // Enable scroll zoom and drag pan
|
|
17
|
+
animation: boolean = true; // Animate candle appearance
|
|
18
|
+
```
|
|
19
|
+
|
|
20
|
+
## Types
|
|
21
|
+
|
|
22
|
+
```typescript
|
|
23
|
+
interface CandleData {
|
|
24
|
+
date: string | number | Date;
|
|
25
|
+
open: number;
|
|
26
|
+
high: number;
|
|
27
|
+
low: number;
|
|
28
|
+
close: number;
|
|
29
|
+
volume?: number;
|
|
30
|
+
}
|
|
31
|
+
```
|
|
32
|
+
|
|
33
|
+
## Methods
|
|
34
|
+
|
|
35
|
+
```typescript
|
|
36
|
+
resetZoom(): void; // Show all data
|
|
37
|
+
zoomTo(startIndex: number, endIndex: number): void; // Zoom to range
|
|
38
|
+
```
|
|
39
|
+
|
|
40
|
+
## Events
|
|
41
|
+
|
|
42
|
+
```typescript
|
|
43
|
+
'@snice/candle-click': { candle: CandleData; index: number }
|
|
44
|
+
'@snice/candle-hover': { candle: CandleData; index: number }
|
|
45
|
+
'@snice/crosshair-move': { price: number; date: string; x: number; y: number }
|
|
46
|
+
```
|
|
47
|
+
|
|
48
|
+
## Usage
|
|
49
|
+
|
|
50
|
+
```html
|
|
51
|
+
<snice-candlestick id="chart" show-volume></snice-candlestick>
|
|
52
|
+
|
|
53
|
+
<script>
|
|
54
|
+
chart.data = [
|
|
55
|
+
{ date: '2024-01-01', open: 100, high: 110, low: 95, close: 105, volume: 500000 },
|
|
56
|
+
{ date: '2024-01-02', open: 105, high: 115, low: 100, close: 98, volume: 600000 },
|
|
57
|
+
];
|
|
58
|
+
</script>
|
|
59
|
+
```
|
|
60
|
+
|
|
61
|
+
## Features
|
|
62
|
+
|
|
63
|
+
- SVG candlestick bodies with wicks (high/low shadows)
|
|
64
|
+
- Green bullish / red bearish coloring (customizable)
|
|
65
|
+
- Optional volume bars below price chart
|
|
66
|
+
- Horizontal grid lines
|
|
67
|
+
- Y-axis price labels (number/currency/percent)
|
|
68
|
+
- X-axis date labels with smart formatting
|
|
69
|
+
- Crosshair with price/date readout
|
|
70
|
+
- OHLC + volume tooltip on hover
|
|
71
|
+
- Scroll to zoom, drag to pan
|
|
72
|
+
- Responsive via ResizeObserver
|
|
73
|
+
- Entrance animation with staggered delays
|
|
74
|
+
- Accessible: role="img" with aria-label
|
|
75
|
+
|
|
76
|
+
## CSS Custom Properties
|
|
77
|
+
|
|
78
|
+
- `--snice-candlestick-bullish` — bullish candle color (default: green)
|
|
79
|
+
- `--snice-candlestick-bearish` — bearish candle color (default: red)
|
|
@@ -0,0 +1,86 @@
|
|
|
1
|
+
# snice-funnel
|
|
2
|
+
|
|
3
|
+
SVG-based funnel chart for conversion tracking and pipeline visualization.
|
|
4
|
+
|
|
5
|
+
## Properties
|
|
6
|
+
|
|
7
|
+
```typescript
|
|
8
|
+
data: FunnelStage[] = []; // Array of { label, value, color? }
|
|
9
|
+
variant: 'default'|'gradient' = 'default';
|
|
10
|
+
orientation: 'vertical'|'horizontal' = 'vertical';
|
|
11
|
+
showLabels: boolean = true; // attribute: show-labels
|
|
12
|
+
showValues: boolean = true; // attribute: show-values
|
|
13
|
+
showPercentages: boolean = true; // attribute: show-percentages
|
|
14
|
+
animation: boolean = false;
|
|
15
|
+
```
|
|
16
|
+
|
|
17
|
+
## Types
|
|
18
|
+
|
|
19
|
+
```typescript
|
|
20
|
+
interface FunnelStage {
|
|
21
|
+
label: string;
|
|
22
|
+
value: number;
|
|
23
|
+
color?: string;
|
|
24
|
+
}
|
|
25
|
+
```
|
|
26
|
+
|
|
27
|
+
## Methods
|
|
28
|
+
|
|
29
|
+
```typescript
|
|
30
|
+
setStages(stages: FunnelStage[]): void;
|
|
31
|
+
exportImage(format?: 'png' | 'svg'): string; // returns data URL
|
|
32
|
+
```
|
|
33
|
+
|
|
34
|
+
## Events
|
|
35
|
+
|
|
36
|
+
```typescript
|
|
37
|
+
'funnel-click': CustomEvent<{ stage: FunnelStage; index: number }>
|
|
38
|
+
'funnel-hover': CustomEvent<{ stage: FunnelStage; index: number }>
|
|
39
|
+
```
|
|
40
|
+
|
|
41
|
+
## Usage
|
|
42
|
+
|
|
43
|
+
```html
|
|
44
|
+
<!-- Basic -->
|
|
45
|
+
<snice-funnel id="f1"></snice-funnel>
|
|
46
|
+
<script>
|
|
47
|
+
document.getElementById('f1').data = [
|
|
48
|
+
{ label: 'Visitors', value: 10000 },
|
|
49
|
+
{ label: 'Leads', value: 5000 },
|
|
50
|
+
{ label: 'Customers', value: 500 },
|
|
51
|
+
];
|
|
52
|
+
</script>
|
|
53
|
+
|
|
54
|
+
<!-- Gradient variant -->
|
|
55
|
+
<snice-funnel variant="gradient"></snice-funnel>
|
|
56
|
+
|
|
57
|
+
<!-- Horizontal -->
|
|
58
|
+
<snice-funnel orientation="horizontal"></snice-funnel>
|
|
59
|
+
|
|
60
|
+
<!-- Custom colors -->
|
|
61
|
+
data = [
|
|
62
|
+
{ label: 'A', value: 100, color: 'rgb(37 99 235)' },
|
|
63
|
+
{ label: 'B', value: 50, color: 'rgb(22 163 74)' },
|
|
64
|
+
]
|
|
65
|
+
|
|
66
|
+
<!-- Hide elements -->
|
|
67
|
+
<snice-funnel show-labels="false" show-values="false"></snice-funnel>
|
|
68
|
+
|
|
69
|
+
<!-- With animation -->
|
|
70
|
+
<snice-funnel animation></snice-funnel>
|
|
71
|
+
```
|
|
72
|
+
|
|
73
|
+
## Features
|
|
74
|
+
|
|
75
|
+
- SVG trapezoid shapes per stage
|
|
76
|
+
- Vertical (default) and horizontal orientation
|
|
77
|
+
- 2 variants: default (distinct colors), gradient (opacity fade)
|
|
78
|
+
- Custom color per stage, falls back to theme palette
|
|
79
|
+
- Labels, values (auto-formatted K/M), percentages
|
|
80
|
+
- Tooltip on hover
|
|
81
|
+
- Click + hover events
|
|
82
|
+
- Keyboard accessible (Enter/Space)
|
|
83
|
+
- ARIA: role="img" on SVG, role="button" + aria-label on stages
|
|
84
|
+
- CSS animation on initial render
|
|
85
|
+
- Responsive via SVG viewBox
|
|
86
|
+
- Works without theme (CSS fallbacks)
|
|
@@ -0,0 +1,87 @@
|
|
|
1
|
+
# snice-network-graph
|
|
2
|
+
|
|
3
|
+
SVG-based force-directed network/relationship graph visualization.
|
|
4
|
+
|
|
5
|
+
## Properties
|
|
6
|
+
|
|
7
|
+
```typescript
|
|
8
|
+
data: NetworkGraphData = { nodes: [], edges: [] };
|
|
9
|
+
layout: 'force'|'circular'|'grid' = 'force';
|
|
10
|
+
chargeStrength: number = -300; // attribute: charge-strength
|
|
11
|
+
linkDistance: number = 80; // attribute: link-distance
|
|
12
|
+
zoomEnabled: boolean = true; // attribute: zoom-enabled
|
|
13
|
+
dragEnabled: boolean = true; // attribute: drag-enabled
|
|
14
|
+
showLabels: boolean = true; // attribute: show-labels
|
|
15
|
+
animation: boolean = true;
|
|
16
|
+
```
|
|
17
|
+
|
|
18
|
+
## Types
|
|
19
|
+
|
|
20
|
+
```typescript
|
|
21
|
+
interface NetworkNode {
|
|
22
|
+
id: string;
|
|
23
|
+
label?: string;
|
|
24
|
+
group?: string;
|
|
25
|
+
size?: number;
|
|
26
|
+
color?: string;
|
|
27
|
+
x?: number;
|
|
28
|
+
y?: number;
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
interface NetworkEdge {
|
|
32
|
+
source: string;
|
|
33
|
+
target: string;
|
|
34
|
+
label?: string;
|
|
35
|
+
weight?: number;
|
|
36
|
+
color?: string;
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
interface NetworkGraphData {
|
|
40
|
+
nodes: NetworkNode[];
|
|
41
|
+
edges: NetworkEdge[];
|
|
42
|
+
}
|
|
43
|
+
```
|
|
44
|
+
|
|
45
|
+
## Events
|
|
46
|
+
|
|
47
|
+
```typescript
|
|
48
|
+
'@snice/node-click': { node: NetworkNode }
|
|
49
|
+
'@snice/edge-click': { edge: NetworkEdge }
|
|
50
|
+
'@snice/node-drag': { node: NetworkNode; x: number; y: number }
|
|
51
|
+
'@snice/graph-zoom': { scale: number; x: number; y: number }
|
|
52
|
+
```
|
|
53
|
+
|
|
54
|
+
## Usage
|
|
55
|
+
|
|
56
|
+
```html
|
|
57
|
+
<snice-network-graph id="graph" layout="force" show-labels></snice-network-graph>
|
|
58
|
+
|
|
59
|
+
<script>
|
|
60
|
+
graph.data = {
|
|
61
|
+
nodes: [
|
|
62
|
+
{ id: 'a', label: 'Node A', group: 'g1' },
|
|
63
|
+
{ id: 'b', label: 'Node B', group: 'g2' },
|
|
64
|
+
],
|
|
65
|
+
edges: [
|
|
66
|
+
{ source: 'a', target: 'b', label: 'connects' },
|
|
67
|
+
],
|
|
68
|
+
};
|
|
69
|
+
</script>
|
|
70
|
+
```
|
|
71
|
+
|
|
72
|
+
## Features
|
|
73
|
+
|
|
74
|
+
- Force-directed layout simulation (repulsion + attraction + centering)
|
|
75
|
+
- Circular and grid static layouts
|
|
76
|
+
- Zoom and pan (mouse wheel + drag on background)
|
|
77
|
+
- Draggable nodes (pin on drag, double-click to unpin)
|
|
78
|
+
- Curves for multi-edges between same node pairs
|
|
79
|
+
- Node sizing by degree or custom `size`
|
|
80
|
+
- Color coding by `group` with 10-color palette
|
|
81
|
+
- Custom colors on individual nodes/edges
|
|
82
|
+
- Edge weight as stroke width
|
|
83
|
+
- Labels on nodes and edges
|
|
84
|
+
- Hover highlighting (connected subgraph, dimmed unconnected)
|
|
85
|
+
- Tooltips showing label and degree
|
|
86
|
+
- Responsive sizing via ResizeObserver
|
|
87
|
+
- Accessible: role="img" with aria-label
|
|
@@ -0,0 +1,63 @@
|
|
|
1
|
+
# snice-sankey
|
|
2
|
+
|
|
3
|
+
SVG-based Sankey diagram for flow visualization between categories.
|
|
4
|
+
|
|
5
|
+
## Properties
|
|
6
|
+
|
|
7
|
+
```typescript
|
|
8
|
+
data: SankeyData = { nodes: [], links: [] };
|
|
9
|
+
nodeWidth: number = 20;
|
|
10
|
+
nodePadding: number = 10;
|
|
11
|
+
alignment: 'left'|'right'|'center'|'justify' = 'justify';
|
|
12
|
+
showLabels: boolean = true;
|
|
13
|
+
showValues: boolean = true;
|
|
14
|
+
animation: boolean = false;
|
|
15
|
+
```
|
|
16
|
+
|
|
17
|
+
## Types
|
|
18
|
+
|
|
19
|
+
```typescript
|
|
20
|
+
interface SankeyData {
|
|
21
|
+
nodes: SankeyNode[];
|
|
22
|
+
links: SankeyLink[];
|
|
23
|
+
}
|
|
24
|
+
interface SankeyNode { id: string; label?: string; color?: string; }
|
|
25
|
+
interface SankeyLink { source: string; target: string; value: number; color?: string; }
|
|
26
|
+
```
|
|
27
|
+
|
|
28
|
+
## Events
|
|
29
|
+
|
|
30
|
+
- `@snice/sankey-node-click` - `{ node: SankeyNode }` - Node clicked
|
|
31
|
+
- `@snice/sankey-link-click` - `{ link: SankeyLink }` - Link clicked
|
|
32
|
+
- `@snice/sankey-hover` - `{ type: 'node'|'link', item: SankeyNode|SankeyLink } | null` - Hover change
|
|
33
|
+
|
|
34
|
+
## Usage
|
|
35
|
+
|
|
36
|
+
```html
|
|
37
|
+
<snice-sankey id="my-sankey" show-labels show-values animation></snice-sankey>
|
|
38
|
+
|
|
39
|
+
<script>
|
|
40
|
+
document.getElementById('my-sankey').data = {
|
|
41
|
+
nodes: [
|
|
42
|
+
{ id: 'a', label: 'Source', color: '#2196f3' },
|
|
43
|
+
{ id: 'b', label: 'Target', color: '#4caf50' }
|
|
44
|
+
],
|
|
45
|
+
links: [
|
|
46
|
+
{ source: 'a', target: 'b', value: 100 }
|
|
47
|
+
]
|
|
48
|
+
};
|
|
49
|
+
</script>
|
|
50
|
+
```
|
|
51
|
+
|
|
52
|
+
## Features
|
|
53
|
+
|
|
54
|
+
- SVG rendering with curved bezier link paths
|
|
55
|
+
- Sankey layout algorithm with iterative node relaxation
|
|
56
|
+
- Link width proportional to flow value
|
|
57
|
+
- Hover highlighting (dims non-connected nodes/links)
|
|
58
|
+
- Tooltips on hover for nodes and links
|
|
59
|
+
- Responsive sizing via ResizeObserver
|
|
60
|
+
- Animation on initial render
|
|
61
|
+
- 4 alignment modes
|
|
62
|
+
- Custom node/link colors
|
|
63
|
+
- Accessible: role="img" with aria-label
|
|
@@ -0,0 +1,78 @@
|
|
|
1
|
+
# snice-time-range-picker
|
|
2
|
+
|
|
3
|
+
Vertically stacked time slot picker with click-and-drag range selection.
|
|
4
|
+
|
|
5
|
+
## Properties
|
|
6
|
+
|
|
7
|
+
```typescript
|
|
8
|
+
granularity: 5 | 15 | 30 | 60 = 15; // Slot interval in minutes
|
|
9
|
+
startTime: string = '00:00'; // Day start (attribute: start-time)
|
|
10
|
+
endTime: string = '23:59'; // Day end (attribute: end-time)
|
|
11
|
+
value: string = ''; // JSON array of TimeRange[]
|
|
12
|
+
disabledRanges: string = ''; // JSON array of TimeRange[] (attribute: disabled-ranges)
|
|
13
|
+
format: '12h' | '24h' = '24h'; // Time display format
|
|
14
|
+
multiple: boolean = false; // Allow multiple non-contiguous ranges
|
|
15
|
+
readonly: boolean = false;
|
|
16
|
+
disabled: boolean = false;
|
|
17
|
+
```
|
|
18
|
+
|
|
19
|
+
## Types
|
|
20
|
+
|
|
21
|
+
```typescript
|
|
22
|
+
interface TimeRange { start: string; end: string; }
|
|
23
|
+
```
|
|
24
|
+
|
|
25
|
+
## Methods
|
|
26
|
+
|
|
27
|
+
- `getSelectedRanges(): TimeRange[]` - Get current selections
|
|
28
|
+
- `setSelectedRanges(ranges: TimeRange[]): void` - Set selections programmatically
|
|
29
|
+
- `clearSelection(): void` - Clear all selections
|
|
30
|
+
- `isSlotDisabled(time: string): boolean` - Check if time slot is disabled
|
|
31
|
+
|
|
32
|
+
## Events
|
|
33
|
+
|
|
34
|
+
- `@snice/time-range-change` - `{ranges: TimeRange[], component}`
|
|
35
|
+
- `@snice/time-range-select` - `{start: string, component}` - Drag begins
|
|
36
|
+
- `@snice/time-range-complete` - `{range: TimeRange, ranges: TimeRange[], component}` - Drag ends
|
|
37
|
+
|
|
38
|
+
## Usage
|
|
39
|
+
|
|
40
|
+
```html
|
|
41
|
+
<!-- Basic -->
|
|
42
|
+
<snice-time-range-picker start-time="08:00" end-time="18:00"></snice-time-range-picker>
|
|
43
|
+
|
|
44
|
+
<!-- 12h format, 30min granularity -->
|
|
45
|
+
<snice-time-range-picker granularity="30" format="12h"></snice-time-range-picker>
|
|
46
|
+
|
|
47
|
+
<!-- With disabled ranges -->
|
|
48
|
+
<snice-time-range-picker
|
|
49
|
+
disabled-ranges='[{"start":"12:00","end":"13:00"}]'>
|
|
50
|
+
</snice-time-range-picker>
|
|
51
|
+
|
|
52
|
+
<!-- Pre-selected value -->
|
|
53
|
+
<snice-time-range-picker
|
|
54
|
+
value='[{"start":"09:00","end":"11:00"}]'>
|
|
55
|
+
</snice-time-range-picker>
|
|
56
|
+
|
|
57
|
+
<!-- Multiple selection -->
|
|
58
|
+
<snice-time-range-picker multiple></snice-time-range-picker>
|
|
59
|
+
|
|
60
|
+
<!-- Event handling -->
|
|
61
|
+
<script>
|
|
62
|
+
picker.addEventListener('@snice/time-range-change', (e) => {
|
|
63
|
+
console.log(e.detail.ranges);
|
|
64
|
+
});
|
|
65
|
+
</script>
|
|
66
|
+
```
|
|
67
|
+
|
|
68
|
+
## Features
|
|
69
|
+
|
|
70
|
+
- Click and drag to select time ranges
|
|
71
|
+
- Single click for individual slot
|
|
72
|
+
- Keyboard navigation (Enter/Space to select, arrows to navigate, Escape to clear)
|
|
73
|
+
- Configurable granularity (5/15/30/60 min)
|
|
74
|
+
- 12h/24h time format
|
|
75
|
+
- Disabled time slots
|
|
76
|
+
- Multiple selection mode
|
|
77
|
+
- Touch support
|
|
78
|
+
- ARIA attributes for accessibility
|
|
@@ -0,0 +1,78 @@
|
|
|
1
|
+
# snice-treemap
|
|
2
|
+
|
|
3
|
+
SVG-based treemap visualization for hierarchical data as nested rectangles.
|
|
4
|
+
|
|
5
|
+
## Properties
|
|
6
|
+
|
|
7
|
+
```typescript
|
|
8
|
+
data: TreemapNode = { label: '', value: 0 };
|
|
9
|
+
showLabels: boolean = true; // attribute: show-labels
|
|
10
|
+
showValues: boolean = false; // attribute: show-values
|
|
11
|
+
colorScheme: TreemapColorScheme = 'default'; // attribute: color-scheme
|
|
12
|
+
padding: number = 2;
|
|
13
|
+
animation: boolean = true;
|
|
14
|
+
drillPath: TreemapNode[]; // read-only, current drill path
|
|
15
|
+
```
|
|
16
|
+
|
|
17
|
+
## Types
|
|
18
|
+
|
|
19
|
+
```typescript
|
|
20
|
+
interface TreemapNode {
|
|
21
|
+
label: string;
|
|
22
|
+
value: number;
|
|
23
|
+
children?: TreemapNode[];
|
|
24
|
+
color?: string;
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
type TreemapColorScheme = 'default' | 'blue' | 'green' | 'purple' | 'orange' | 'warm' | 'cool' | 'rainbow';
|
|
28
|
+
```
|
|
29
|
+
|
|
30
|
+
## Methods
|
|
31
|
+
|
|
32
|
+
```typescript
|
|
33
|
+
drillDown(node: TreemapNode): void; // drill into node's children
|
|
34
|
+
drillUp(): void; // go back one level
|
|
35
|
+
drillToRoot(): void; // reset to root
|
|
36
|
+
```
|
|
37
|
+
|
|
38
|
+
## Events
|
|
39
|
+
|
|
40
|
+
```typescript
|
|
41
|
+
'@snice/treemap-click': CustomEvent<{ node: TreemapNode; depth: number }>;
|
|
42
|
+
'@snice/treemap-hover': CustomEvent<{ node: TreemapNode; depth: number } | null>;
|
|
43
|
+
'@snice/treemap-drill': CustomEvent<{ node: TreemapNode; path: TreemapNode[] }>;
|
|
44
|
+
```
|
|
45
|
+
|
|
46
|
+
## Usage
|
|
47
|
+
|
|
48
|
+
```html
|
|
49
|
+
<!-- Basic -->
|
|
50
|
+
<snice-treemap show-labels show-values></snice-treemap>
|
|
51
|
+
|
|
52
|
+
<!-- Color scheme -->
|
|
53
|
+
<snice-treemap show-labels color-scheme="blue"></snice-treemap>
|
|
54
|
+
|
|
55
|
+
<!-- Set data via JS -->
|
|
56
|
+
<script>
|
|
57
|
+
treemap.data = {
|
|
58
|
+
label: 'Root',
|
|
59
|
+
value: 0,
|
|
60
|
+
children: [
|
|
61
|
+
{ label: 'A', value: 50 },
|
|
62
|
+
{ label: 'B', value: 30 },
|
|
63
|
+
{ label: 'C', value: 20 },
|
|
64
|
+
]
|
|
65
|
+
};
|
|
66
|
+
</script>
|
|
67
|
+
```
|
|
68
|
+
|
|
69
|
+
## Features
|
|
70
|
+
|
|
71
|
+
- Squarified treemap layout algorithm for optimal aspect ratios
|
|
72
|
+
- 8 color schemes + custom per-node colors
|
|
73
|
+
- Drill-down into child nodes with breadcrumb navigation
|
|
74
|
+
- Tooltips on hover
|
|
75
|
+
- Labels auto-hide when rectangles are too small
|
|
76
|
+
- Responsive sizing via ResizeObserver
|
|
77
|
+
- Animated transitions
|
|
78
|
+
- Accessible: role="img" with aria-label
|