@lifecorner/angular-ui-kit 3.4.1 → 3.5.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +12 -2
- package/fesm2022/lifecorner-angular-ui-kit-accordion.mjs +454 -0
- package/fesm2022/lifecorner-angular-ui-kit-accordion.mjs.map +1 -0
- package/fesm2022/lifecorner-angular-ui-kit-alert.mjs +297 -0
- package/fesm2022/lifecorner-angular-ui-kit-alert.mjs.map +1 -0
- package/fesm2022/lifecorner-angular-ui-kit-app-shell.mjs +190 -0
- package/fesm2022/lifecorner-angular-ui-kit-app-shell.mjs.map +1 -0
- package/fesm2022/lifecorner-angular-ui-kit-area-chart.mjs +446 -0
- package/fesm2022/lifecorner-angular-ui-kit-area-chart.mjs.map +1 -0
- package/fesm2022/lifecorner-angular-ui-kit-avatar-group.mjs +158 -0
- package/fesm2022/lifecorner-angular-ui-kit-avatar-group.mjs.map +1 -0
- package/fesm2022/lifecorner-angular-ui-kit-avatar.mjs +216 -0
- package/fesm2022/lifecorner-angular-ui-kit-avatar.mjs.map +1 -0
- package/fesm2022/lifecorner-angular-ui-kit-badge.mjs +121 -0
- package/fesm2022/lifecorner-angular-ui-kit-badge.mjs.map +1 -0
- package/fesm2022/lifecorner-angular-ui-kit-bar-chart.mjs +360 -0
- package/fesm2022/lifecorner-angular-ui-kit-bar-chart.mjs.map +1 -0
- package/fesm2022/lifecorner-angular-ui-kit-bottom-nav.mjs +344 -0
- package/fesm2022/lifecorner-angular-ui-kit-bottom-nav.mjs.map +1 -0
- package/fesm2022/lifecorner-angular-ui-kit-breadcrumbs.mjs +191 -0
- package/fesm2022/lifecorner-angular-ui-kit-breadcrumbs.mjs.map +1 -0
- package/fesm2022/lifecorner-angular-ui-kit-button.mjs +423 -0
- package/fesm2022/lifecorner-angular-ui-kit-button.mjs.map +1 -0
- package/fesm2022/lifecorner-angular-ui-kit-calendar.mjs +368 -0
- package/fesm2022/lifecorner-angular-ui-kit-calendar.mjs.map +1 -0
- package/fesm2022/lifecorner-angular-ui-kit-callout.mjs +203 -0
- package/fesm2022/lifecorner-angular-ui-kit-callout.mjs.map +1 -0
- package/fesm2022/lifecorner-angular-ui-kit-card.mjs +323 -0
- package/fesm2022/lifecorner-angular-ui-kit-card.mjs.map +1 -0
- package/fesm2022/lifecorner-angular-ui-kit-chat.mjs +790 -0
- package/fesm2022/lifecorner-angular-ui-kit-chat.mjs.map +1 -0
- package/fesm2022/lifecorner-angular-ui-kit-checkbox.mjs +325 -0
- package/fesm2022/lifecorner-angular-ui-kit-checkbox.mjs.map +1 -0
- package/fesm2022/lifecorner-angular-ui-kit-chip.mjs +214 -0
- package/fesm2022/lifecorner-angular-ui-kit-chip.mjs.map +1 -0
- package/fesm2022/lifecorner-angular-ui-kit-choice-prompt.mjs +375 -0
- package/fesm2022/lifecorner-angular-ui-kit-choice-prompt.mjs.map +1 -0
- package/fesm2022/lifecorner-angular-ui-kit-code-block.mjs +518 -0
- package/fesm2022/lifecorner-angular-ui-kit-code-block.mjs.map +1 -0
- package/fesm2022/lifecorner-angular-ui-kit-color-picker.mjs +278 -0
- package/fesm2022/lifecorner-angular-ui-kit-color-picker.mjs.map +1 -0
- package/fesm2022/lifecorner-angular-ui-kit-combobox.mjs +688 -0
- package/fesm2022/lifecorner-angular-ui-kit-combobox.mjs.map +1 -0
- package/fesm2022/lifecorner-angular-ui-kit-confirm-dialog.mjs +494 -0
- package/fesm2022/lifecorner-angular-ui-kit-confirm-dialog.mjs.map +1 -0
- package/fesm2022/lifecorner-angular-ui-kit-container.mjs +103 -0
- package/fesm2022/lifecorner-angular-ui-kit-container.mjs.map +1 -0
- package/fesm2022/lifecorner-angular-ui-kit-copy-field.mjs +308 -0
- package/fesm2022/lifecorner-angular-ui-kit-copy-field.mjs.map +1 -0
- package/fesm2022/lifecorner-angular-ui-kit-date-range-picker.mjs +466 -0
- package/fesm2022/lifecorner-angular-ui-kit-date-range-picker.mjs.map +1 -0
- package/fesm2022/lifecorner-angular-ui-kit-datepicker.mjs +810 -0
- package/fesm2022/lifecorner-angular-ui-kit-datepicker.mjs.map +1 -0
- package/fesm2022/lifecorner-angular-ui-kit-dependency-viewer.mjs +1761 -0
- package/fesm2022/lifecorner-angular-ui-kit-dependency-viewer.mjs.map +1 -0
- package/fesm2022/lifecorner-angular-ui-kit-description-list.mjs +165 -0
- package/fesm2022/lifecorner-angular-ui-kit-description-list.mjs.map +1 -0
- package/fesm2022/lifecorner-angular-ui-kit-diff-viewer.mjs +356 -0
- package/fesm2022/lifecorner-angular-ui-kit-diff-viewer.mjs.map +1 -0
- package/fesm2022/lifecorner-angular-ui-kit-divider.mjs +119 -0
- package/fesm2022/lifecorner-angular-ui-kit-divider.mjs.map +1 -0
- package/fesm2022/lifecorner-angular-ui-kit-document-viewer.mjs +762 -0
- package/fesm2022/lifecorner-angular-ui-kit-document-viewer.mjs.map +1 -0
- package/fesm2022/lifecorner-angular-ui-kit-donut-chart.mjs +255 -0
- package/fesm2022/lifecorner-angular-ui-kit-donut-chart.mjs.map +1 -0
- package/fesm2022/lifecorner-angular-ui-kit-drawer.mjs +308 -0
- package/fesm2022/lifecorner-angular-ui-kit-drawer.mjs.map +1 -0
- package/fesm2022/lifecorner-angular-ui-kit-email-input.mjs +519 -0
- package/fesm2022/lifecorner-angular-ui-kit-email-input.mjs.map +1 -0
- package/fesm2022/lifecorner-angular-ui-kit-empty-state.mjs +143 -0
- package/fesm2022/lifecorner-angular-ui-kit-empty-state.mjs.map +1 -0
- package/fesm2022/lifecorner-angular-ui-kit-error-display.mjs +306 -0
- package/fesm2022/lifecorner-angular-ui-kit-error-display.mjs.map +1 -0
- package/fesm2022/lifecorner-angular-ui-kit-field-group.mjs +154 -0
- package/fesm2022/lifecorner-angular-ui-kit-field-group.mjs.map +1 -0
- package/fesm2022/lifecorner-angular-ui-kit-file-upload.mjs +281 -0
- package/fesm2022/lifecorner-angular-ui-kit-file-upload.mjs.map +1 -0
- package/fesm2022/lifecorner-angular-ui-kit-filter-bar.mjs +258 -0
- package/fesm2022/lifecorner-angular-ui-kit-filter-bar.mjs.map +1 -0
- package/fesm2022/lifecorner-angular-ui-kit-footer.mjs +200 -0
- package/fesm2022/lifecorner-angular-ui-kit-footer.mjs.map +1 -0
- package/fesm2022/lifecorner-angular-ui-kit-funnel-chart.mjs +292 -0
- package/fesm2022/lifecorner-angular-ui-kit-funnel-chart.mjs.map +1 -0
- package/fesm2022/lifecorner-angular-ui-kit-gallery.mjs +563 -0
- package/fesm2022/lifecorner-angular-ui-kit-gallery.mjs.map +1 -0
- package/fesm2022/lifecorner-angular-ui-kit-gantt-chart.mjs +314 -0
- package/fesm2022/lifecorner-angular-ui-kit-gantt-chart.mjs.map +1 -0
- package/fesm2022/lifecorner-angular-ui-kit-gauge.mjs +265 -0
- package/fesm2022/lifecorner-angular-ui-kit-gauge.mjs.map +1 -0
- package/fesm2022/lifecorner-angular-ui-kit-header.mjs +955 -0
- package/fesm2022/lifecorner-angular-ui-kit-header.mjs.map +1 -0
- package/fesm2022/lifecorner-angular-ui-kit-heatmap.mjs +305 -0
- package/fesm2022/lifecorner-angular-ui-kit-heatmap.mjs.map +1 -0
- package/fesm2022/lifecorner-angular-ui-kit-hero.mjs +168 -0
- package/fesm2022/lifecorner-angular-ui-kit-hero.mjs.map +1 -0
- package/fesm2022/lifecorner-angular-ui-kit-icon-names.mjs +9 -0
- package/fesm2022/lifecorner-angular-ui-kit-icon-names.mjs.map +1 -0
- package/fesm2022/lifecorner-angular-ui-kit-icon.mjs +1026 -0
- package/fesm2022/lifecorner-angular-ui-kit-icon.mjs.map +1 -0
- package/fesm2022/lifecorner-angular-ui-kit-input.mjs +595 -0
- package/fesm2022/lifecorner-angular-ui-kit-input.mjs.map +1 -0
- package/fesm2022/lifecorner-angular-ui-kit-internal-chart.mjs +105 -0
- package/fesm2022/lifecorner-angular-ui-kit-internal-chart.mjs.map +1 -0
- package/fesm2022/lifecorner-angular-ui-kit-internal-overlay.mjs +50 -0
- package/fesm2022/lifecorner-angular-ui-kit-internal-overlay.mjs.map +1 -0
- package/fesm2022/lifecorner-angular-ui-kit-internal-url.mjs +22 -0
- package/fesm2022/lifecorner-angular-ui-kit-internal-url.mjs.map +1 -0
- package/fesm2022/lifecorner-angular-ui-kit-kanban-board.mjs +319 -0
- package/fesm2022/lifecorner-angular-ui-kit-kanban-board.mjs.map +1 -0
- package/fesm2022/lifecorner-angular-ui-kit-line-chart.mjs +413 -0
- package/fesm2022/lifecorner-angular-ui-kit-line-chart.mjs.map +1 -0
- package/fesm2022/lifecorner-angular-ui-kit-list.mjs +338 -0
- package/fesm2022/lifecorner-angular-ui-kit-list.mjs.map +1 -0
- package/fesm2022/lifecorner-angular-ui-kit-log-viewer.mjs +813 -0
- package/fesm2022/lifecorner-angular-ui-kit-log-viewer.mjs.map +1 -0
- package/fesm2022/lifecorner-angular-ui-kit-logo.mjs +226 -0
- package/fesm2022/lifecorner-angular-ui-kit-logo.mjs.map +1 -0
- package/fesm2022/lifecorner-angular-ui-kit-markdown.mjs +756 -0
- package/fesm2022/lifecorner-angular-ui-kit-markdown.mjs.map +1 -0
- package/fesm2022/lifecorner-angular-ui-kit-menu.mjs +321 -0
- package/fesm2022/lifecorner-angular-ui-kit-menu.mjs.map +1 -0
- package/fesm2022/lifecorner-angular-ui-kit-modal.mjs +329 -0
- package/fesm2022/lifecorner-angular-ui-kit-modal.mjs.map +1 -0
- package/fesm2022/lifecorner-angular-ui-kit-models.mjs +0 -0
- package/fesm2022/lifecorner-angular-ui-kit-next-step-card.mjs +419 -0
- package/fesm2022/lifecorner-angular-ui-kit-next-step-card.mjs.map +1 -0
- package/fesm2022/lifecorner-angular-ui-kit-notification-center.mjs +644 -0
- package/fesm2022/lifecorner-angular-ui-kit-notification-center.mjs.map +1 -0
- package/fesm2022/lifecorner-angular-ui-kit-number-input.mjs +401 -0
- package/fesm2022/lifecorner-angular-ui-kit-number-input.mjs.map +1 -0
- package/fesm2022/lifecorner-angular-ui-kit-page-header.mjs +266 -0
- package/fesm2022/lifecorner-angular-ui-kit-page-header.mjs.map +1 -0
- package/fesm2022/lifecorner-angular-ui-kit-page-layout.mjs +127 -0
- package/fesm2022/lifecorner-angular-ui-kit-page-layout.mjs.map +1 -0
- package/fesm2022/lifecorner-angular-ui-kit-pagination.mjs +343 -0
- package/fesm2022/lifecorner-angular-ui-kit-pagination.mjs.map +1 -0
- package/fesm2022/lifecorner-angular-ui-kit-password-input.mjs +696 -0
- package/fesm2022/lifecorner-angular-ui-kit-password-input.mjs.map +1 -0
- package/fesm2022/lifecorner-angular-ui-kit-pie-chart.mjs +162 -0
- package/fesm2022/lifecorner-angular-ui-kit-pie-chart.mjs.map +1 -0
- package/fesm2022/lifecorner-angular-ui-kit-pipeline.mjs +159 -0
- package/fesm2022/lifecorner-angular-ui-kit-pipeline.mjs.map +1 -0
- package/fesm2022/lifecorner-angular-ui-kit-popover.mjs +190 -0
- package/fesm2022/lifecorner-angular-ui-kit-popover.mjs.map +1 -0
- package/fesm2022/lifecorner-angular-ui-kit-progress-bar.mjs +190 -0
- package/fesm2022/lifecorner-angular-ui-kit-progress-bar.mjs.map +1 -0
- package/fesm2022/lifecorner-angular-ui-kit-progress-ring.mjs +175 -0
- package/fesm2022/lifecorner-angular-ui-kit-progress-ring.mjs.map +1 -0
- package/fesm2022/lifecorner-angular-ui-kit-provider-button.mjs +255 -0
- package/fesm2022/lifecorner-angular-ui-kit-provider-button.mjs.map +1 -0
- package/fesm2022/lifecorner-angular-ui-kit-radar-chart.mjs +309 -0
- package/fesm2022/lifecorner-angular-ui-kit-radar-chart.mjs.map +1 -0
- package/fesm2022/lifecorner-angular-ui-kit-radio.mjs +708 -0
- package/fesm2022/lifecorner-angular-ui-kit-radio.mjs.map +1 -0
- package/fesm2022/lifecorner-angular-ui-kit-rating.mjs +327 -0
- package/fesm2022/lifecorner-angular-ui-kit-rating.mjs.map +1 -0
- package/fesm2022/lifecorner-angular-ui-kit-rich-text-editor.mjs +718 -0
- package/fesm2022/lifecorner-angular-ui-kit-rich-text-editor.mjs.map +1 -0
- package/fesm2022/lifecorner-angular-ui-kit-scatter-plot.mjs +415 -0
- package/fesm2022/lifecorner-angular-ui-kit-scatter-plot.mjs.map +1 -0
- package/fesm2022/lifecorner-angular-ui-kit-search-input.mjs +290 -0
- package/fesm2022/lifecorner-angular-ui-kit-search-input.mjs.map +1 -0
- package/fesm2022/lifecorner-angular-ui-kit-section.mjs +127 -0
- package/fesm2022/lifecorner-angular-ui-kit-section.mjs.map +1 -0
- package/fesm2022/lifecorner-angular-ui-kit-select.mjs +650 -0
- package/fesm2022/lifecorner-angular-ui-kit-select.mjs.map +1 -0
- package/fesm2022/lifecorner-angular-ui-kit-sidenav.mjs +691 -0
- package/fesm2022/lifecorner-angular-ui-kit-sidenav.mjs.map +1 -0
- package/fesm2022/lifecorner-angular-ui-kit-skeleton.mjs +144 -0
- package/fesm2022/lifecorner-angular-ui-kit-skeleton.mjs.map +1 -0
- package/fesm2022/lifecorner-angular-ui-kit-slider.mjs +204 -0
- package/fesm2022/lifecorner-angular-ui-kit-slider.mjs.map +1 -0
- package/fesm2022/lifecorner-angular-ui-kit-spacer.mjs +73 -0
- package/fesm2022/lifecorner-angular-ui-kit-spacer.mjs.map +1 -0
- package/fesm2022/lifecorner-angular-ui-kit-sparkline.mjs +318 -0
- package/fesm2022/lifecorner-angular-ui-kit-sparkline.mjs.map +1 -0
- package/fesm2022/lifecorner-angular-ui-kit-spinner.mjs +95 -0
- package/fesm2022/lifecorner-angular-ui-kit-spinner.mjs.map +1 -0
- package/fesm2022/lifecorner-angular-ui-kit-split-pane.mjs +298 -0
- package/fesm2022/lifecorner-angular-ui-kit-split-pane.mjs.map +1 -0
- package/fesm2022/lifecorner-angular-ui-kit-stack.mjs +162 -0
- package/fesm2022/lifecorner-angular-ui-kit-stack.mjs.map +1 -0
- package/fesm2022/lifecorner-angular-ui-kit-stacked-bar-chart.mjs +412 -0
- package/fesm2022/lifecorner-angular-ui-kit-stacked-bar-chart.mjs.map +1 -0
- package/fesm2022/lifecorner-angular-ui-kit-stage-list.mjs +186 -0
- package/fesm2022/lifecorner-angular-ui-kit-stage-list.mjs.map +1 -0
- package/fesm2022/lifecorner-angular-ui-kit-stat-trend.mjs +224 -0
- package/fesm2022/lifecorner-angular-ui-kit-stat-trend.mjs.map +1 -0
- package/fesm2022/lifecorner-angular-ui-kit-status-dot.mjs +122 -0
- package/fesm2022/lifecorner-angular-ui-kit-status-dot.mjs.map +1 -0
- package/fesm2022/lifecorner-angular-ui-kit-stepper.mjs +209 -0
- package/fesm2022/lifecorner-angular-ui-kit-stepper.mjs.map +1 -0
- package/fesm2022/lifecorner-angular-ui-kit-switch.mjs +249 -0
- package/fesm2022/lifecorner-angular-ui-kit-switch.mjs.map +1 -0
- package/fesm2022/lifecorner-angular-ui-kit-table.mjs +1434 -0
- package/fesm2022/lifecorner-angular-ui-kit-table.mjs.map +1 -0
- package/fesm2022/lifecorner-angular-ui-kit-tabs.mjs +407 -0
- package/fesm2022/lifecorner-angular-ui-kit-tabs.mjs.map +1 -0
- package/fesm2022/lifecorner-angular-ui-kit-tag-input.mjs +380 -0
- package/fesm2022/lifecorner-angular-ui-kit-tag-input.mjs.map +1 -0
- package/fesm2022/lifecorner-angular-ui-kit-textarea.mjs +440 -0
- package/fesm2022/lifecorner-angular-ui-kit-textarea.mjs.map +1 -0
- package/fesm2022/lifecorner-angular-ui-kit-theme.mjs +145 -0
- package/fesm2022/lifecorner-angular-ui-kit-theme.mjs.map +1 -0
- package/fesm2022/lifecorner-angular-ui-kit-timeline.mjs +262 -0
- package/fesm2022/lifecorner-angular-ui-kit-timeline.mjs.map +1 -0
- package/fesm2022/lifecorner-angular-ui-kit-toast.mjs +352 -0
- package/fesm2022/lifecorner-angular-ui-kit-toast.mjs.map +1 -0
- package/fesm2022/lifecorner-angular-ui-kit-toggle-group.mjs +215 -0
- package/fesm2022/lifecorner-angular-ui-kit-toggle-group.mjs.map +1 -0
- package/fesm2022/lifecorner-angular-ui-kit-tokens.mjs +134 -0
- package/fesm2022/lifecorner-angular-ui-kit-tokens.mjs.map +1 -0
- package/fesm2022/lifecorner-angular-ui-kit-toolbar.mjs +225 -0
- package/fesm2022/lifecorner-angular-ui-kit-toolbar.mjs.map +1 -0
- package/fesm2022/lifecorner-angular-ui-kit-tooltip.mjs +386 -0
- package/fesm2022/lifecorner-angular-ui-kit-tooltip.mjs.map +1 -0
- package/fesm2022/lifecorner-angular-ui-kit-tree-view.mjs +509 -0
- package/fesm2022/lifecorner-angular-ui-kit-tree-view.mjs.map +1 -0
- package/fesm2022/lifecorner-angular-ui-kit-typography.mjs +209 -0
- package/fesm2022/lifecorner-angular-ui-kit-typography.mjs.map +1 -0
- package/fesm2022/lifecorner-angular-ui-kit-verification-code-input.mjs +365 -0
- package/fesm2022/lifecorner-angular-ui-kit-verification-code-input.mjs.map +1 -0
- package/fesm2022/lifecorner-angular-ui-kit-waterfall-chart.mjs +371 -0
- package/fesm2022/lifecorner-angular-ui-kit-waterfall-chart.mjs.map +1 -0
- package/fesm2022/lifecorner-angular-ui-kit.mjs +109 -38925
- package/package.json +449 -1
- package/types/lifecorner-angular-ui-kit-accordion.d.ts +239 -0
- package/types/lifecorner-angular-ui-kit-alert.d.ts +189 -0
- package/types/lifecorner-angular-ui-kit-app-shell.d.ts +148 -0
- package/types/lifecorner-angular-ui-kit-area-chart.d.ts +180 -0
- package/types/lifecorner-angular-ui-kit-avatar-group.d.ts +62 -0
- package/types/lifecorner-angular-ui-kit-avatar.d.ts +131 -0
- package/types/lifecorner-angular-ui-kit-badge.d.ts +59 -0
- package/types/lifecorner-angular-ui-kit-bar-chart.d.ts +157 -0
- package/types/lifecorner-angular-ui-kit-bottom-nav.d.ts +184 -0
- package/types/lifecorner-angular-ui-kit-breadcrumbs.d.ts +55 -0
- package/types/lifecorner-angular-ui-kit-button.d.ts +181 -0
- package/types/lifecorner-angular-ui-kit-calendar.d.ts +136 -0
- package/types/lifecorner-angular-ui-kit-callout.d.ts +77 -0
- package/types/lifecorner-angular-ui-kit-card.d.ts +213 -0
- package/types/lifecorner-angular-ui-kit-chat.d.ts +379 -0
- package/types/lifecorner-angular-ui-kit-checkbox.d.ts +116 -0
- package/types/lifecorner-angular-ui-kit-chip.d.ts +104 -0
- package/types/lifecorner-angular-ui-kit-choice-prompt.d.ts +186 -0
- package/types/lifecorner-angular-ui-kit-code-block.d.ts +85 -0
- package/types/lifecorner-angular-ui-kit-color-picker.d.ts +88 -0
- package/types/lifecorner-angular-ui-kit-combobox.d.ts +222 -0
- package/types/lifecorner-angular-ui-kit-confirm-dialog.d.ts +211 -0
- package/types/lifecorner-angular-ui-kit-container.d.ts +47 -0
- package/types/lifecorner-angular-ui-kit-copy-field.d.ts +89 -0
- package/types/lifecorner-angular-ui-kit-date-range-picker.d.ts +126 -0
- package/types/lifecorner-angular-ui-kit-datepicker.d.ts +363 -0
- package/types/lifecorner-angular-ui-kit-dependency-viewer.d.ts +568 -0
- package/types/lifecorner-angular-ui-kit-description-list.d.ts +137 -0
- package/types/lifecorner-angular-ui-kit-diff-viewer.d.ts +93 -0
- package/types/lifecorner-angular-ui-kit-divider.d.ts +66 -0
- package/types/lifecorner-angular-ui-kit-document-viewer.d.ts +256 -0
- package/types/lifecorner-angular-ui-kit-donut-chart.d.ts +92 -0
- package/types/lifecorner-angular-ui-kit-drawer.d.ts +124 -0
- package/types/lifecorner-angular-ui-kit-email-input.d.ts +292 -0
- package/types/lifecorner-angular-ui-kit-empty-state.d.ts +81 -0
- package/types/lifecorner-angular-ui-kit-error-display.d.ts +157 -0
- package/types/lifecorner-angular-ui-kit-field-group.d.ts +69 -0
- package/types/lifecorner-angular-ui-kit-file-upload.d.ts +122 -0
- package/types/lifecorner-angular-ui-kit-filter-bar.d.ts +116 -0
- package/types/lifecorner-angular-ui-kit-footer.d.ts +97 -0
- package/types/lifecorner-angular-ui-kit-funnel-chart.d.ts +97 -0
- package/types/lifecorner-angular-ui-kit-gallery.d.ts +240 -0
- package/types/lifecorner-angular-ui-kit-gantt-chart.d.ts +133 -0
- package/types/lifecorner-angular-ui-kit-gauge.d.ts +94 -0
- package/types/lifecorner-angular-ui-kit-header.d.ts +496 -0
- package/types/lifecorner-angular-ui-kit-heatmap.d.ts +126 -0
- package/types/lifecorner-angular-ui-kit-hero.d.ts +121 -0
- package/types/lifecorner-angular-ui-kit-icon-names.d.ts +21 -0
- package/types/lifecorner-angular-ui-kit-icon.d.ts +260 -0
- package/types/lifecorner-angular-ui-kit-input.d.ts +346 -0
- package/types/lifecorner-angular-ui-kit-internal-chart.d.ts +86 -0
- package/types/lifecorner-angular-ui-kit-internal-overlay.d.ts +31 -0
- package/types/lifecorner-angular-ui-kit-internal-url.d.ts +22 -0
- package/types/lifecorner-angular-ui-kit-kanban-board.d.ts +111 -0
- package/types/lifecorner-angular-ui-kit-line-chart.d.ts +186 -0
- package/types/lifecorner-angular-ui-kit-list.d.ts +215 -0
- package/types/lifecorner-angular-ui-kit-log-viewer.d.ts +355 -0
- package/types/lifecorner-angular-ui-kit-logo.d.ts +182 -0
- package/types/lifecorner-angular-ui-kit-markdown.d.ts +278 -0
- package/types/lifecorner-angular-ui-kit-menu.d.ts +152 -0
- package/types/lifecorner-angular-ui-kit-modal.d.ts +207 -0
- package/types/lifecorner-angular-ui-kit-models.d.ts +62 -0
- package/types/lifecorner-angular-ui-kit-next-step-card.d.ts +262 -0
- package/types/lifecorner-angular-ui-kit-notification-center.d.ts +237 -0
- package/types/lifecorner-angular-ui-kit-number-input.d.ts +126 -0
- package/types/lifecorner-angular-ui-kit-page-header.d.ts +178 -0
- package/types/lifecorner-angular-ui-kit-page-layout.d.ts +61 -0
- package/types/lifecorner-angular-ui-kit-pagination.d.ts +141 -0
- package/types/lifecorner-angular-ui-kit-password-input.d.ts +361 -0
- package/types/lifecorner-angular-ui-kit-pie-chart.d.ts +58 -0
- package/types/lifecorner-angular-ui-kit-pipeline.d.ts +89 -0
- package/types/lifecorner-angular-ui-kit-popover.d.ts +104 -0
- package/types/lifecorner-angular-ui-kit-progress-bar.d.ts +116 -0
- package/types/lifecorner-angular-ui-kit-progress-ring.d.ts +67 -0
- package/types/lifecorner-angular-ui-kit-provider-button.d.ts +137 -0
- package/types/lifecorner-angular-ui-kit-radar-chart.d.ts +113 -0
- package/types/lifecorner-angular-ui-kit-radio.d.ts +297 -0
- package/types/lifecorner-angular-ui-kit-rating.d.ts +115 -0
- package/types/lifecorner-angular-ui-kit-rich-text-editor.d.ts +226 -0
- package/types/lifecorner-angular-ui-kit-scatter-plot.d.ts +190 -0
- package/types/lifecorner-angular-ui-kit-search-input.d.ts +137 -0
- package/types/lifecorner-angular-ui-kit-section.d.ts +34 -0
- package/types/lifecorner-angular-ui-kit-select.d.ts +274 -0
- package/types/lifecorner-angular-ui-kit-sidenav.d.ts +368 -0
- package/types/lifecorner-angular-ui-kit-skeleton.d.ts +61 -0
- package/types/lifecorner-angular-ui-kit-slider.d.ts +79 -0
- package/types/lifecorner-angular-ui-kit-spacer.d.ts +27 -0
- package/types/lifecorner-angular-ui-kit-sparkline.d.ts +113 -0
- package/types/lifecorner-angular-ui-kit-spinner.d.ts +50 -0
- package/types/lifecorner-angular-ui-kit-split-pane.d.ts +131 -0
- package/types/lifecorner-angular-ui-kit-stack.d.ts +49 -0
- package/types/lifecorner-angular-ui-kit-stacked-bar-chart.d.ts +171 -0
- package/types/lifecorner-angular-ui-kit-stage-list.d.ts +69 -0
- package/types/lifecorner-angular-ui-kit-stat-trend.d.ts +62 -0
- package/types/lifecorner-angular-ui-kit-status-dot.d.ts +62 -0
- package/types/lifecorner-angular-ui-kit-stepper.d.ts +113 -0
- package/types/lifecorner-angular-ui-kit-switch.d.ts +141 -0
- package/types/lifecorner-angular-ui-kit-table.d.ts +632 -0
- package/types/lifecorner-angular-ui-kit-tabs.d.ts +196 -0
- package/types/lifecorner-angular-ui-kit-tag-input.d.ts +123 -0
- package/types/lifecorner-angular-ui-kit-textarea.d.ts +225 -0
- package/types/lifecorner-angular-ui-kit-theme.d.ts +91 -0
- package/types/lifecorner-angular-ui-kit-timeline.d.ts +162 -0
- package/types/lifecorner-angular-ui-kit-toast.d.ts +204 -0
- package/types/lifecorner-angular-ui-kit-toggle-group.d.ts +100 -0
- package/types/lifecorner-angular-ui-kit-tokens.d.ts +134 -0
- package/types/lifecorner-angular-ui-kit-toolbar.d.ts +120 -0
- package/types/lifecorner-angular-ui-kit-tooltip.d.ts +120 -0
- package/types/lifecorner-angular-ui-kit-tree-view.d.ts +231 -0
- package/types/lifecorner-angular-ui-kit-typography.d.ts +126 -0
- package/types/lifecorner-angular-ui-kit-verification-code-input.d.ts +187 -0
- package/types/lifecorner-angular-ui-kit-waterfall-chart.d.ts +163 -0
- package/types/lifecorner-angular-ui-kit.d.ts +109 -17401
- package/fesm2022/lifecorner-angular-ui-kit.mjs.map +0 -1
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"lifecorner-angular-ui-kit-rich-text-editor.mjs","names":[],"sources":["../../../../libs/angular-ui-kit/src/lib/rich-text-editor/rich-text-editor.component.ts","../../../../libs/angular-ui-kit/src/lib/rich-text-editor/rich-text-editor.component.html"],"sourcesContent":["import {\n Component,\n ChangeDetectionStrategy,\n ElementRef,\n SecurityContext,\n computed,\n effect,\n forwardRef,\n inject,\n input,\n linkedSignal,\n output,\n signal,\n untracked,\n viewChild,\n} from '@angular/core';\nimport { CommonModule } from '@angular/common';\nimport { ControlValueAccessor, NG_VALUE_ACCESSOR } from '@angular/forms';\nimport { DomSanitizer } from '@angular/platform-browser';\nimport { isSafeImageUrl, isSafeLinkUrl } from '@lifecorner/angular-ui-kit/internal/url';\n\nexport type RichTextEditorMode = 'rich' | 'markdown' | 'split';\nexport type ToolbarAction =\n | 'bold'\n | 'italic'\n | 'underline'\n | 'strikethrough'\n | 'h1'\n | 'h2'\n | 'h3'\n | 'ul'\n | 'ol'\n | 'blockquote'\n | 'code'\n | 'codeblock'\n | 'link'\n | 'image'\n | 'hr';\n\nexport interface ToolbarConfig {\n actions: ToolbarAction[];\n}\n\nconst HTML_ESCAPES: Record<string, string> = {\n '&': '&',\n '<': '<',\n '>': '>',\n '\"': '"',\n \"'\": ''',\n};\n\n/** Escapes text for HTML — every character that could open a tag or an attribute. */\nfunction escapeHtml(text: string): string {\n return text.replace(/[&<>\"']/g, (c) => HTML_ESCAPES[c]);\n}\n\n/**\n * The URL as it may go into `href`/`src`, or null if it must not: only relative\n * URLs and the allow-listed schemes pass (see `safe-url.ts`), so a link in\n * user-supplied markdown can never run script when clicked.\n */\nfunction safeUrl(url: string, image = false): string | null {\n const value = url.trim();\n if (!value) return null;\n return (image ? isSafeImageUrl(value) : isSafeLinkUrl(value)) ? value : null;\n}\n\nconst DEFAULT_TOOLBAR: ToolbarConfig = {\n actions: [\n 'bold',\n 'italic',\n 'underline',\n 'strikethrough',\n 'h1',\n 'h2',\n 'h3',\n 'ul',\n 'ol',\n 'blockquote',\n 'code',\n 'codeblock',\n 'link',\n 'hr',\n ],\n};\n\n/**\n * Rich Text Editor with Markdown support.\n *\n * Supports three modes:\n * - `rich`: WYSIWYG editing with toolbar\n * - `markdown`: Raw markdown editing with syntax highlighting\n * - `split`: Side-by-side markdown and preview\n *\n * Implements ControlValueAccessor for reactive form integration.\n * The value is always stored as Markdown.\n *\n * The built-in markdown → HTML conversion escapes the source before it applies\n * any markup and only lets http(s)/mailto/tel and relative URLs through as\n * links, so markdown that arrives from a server or another user cannot inject\n * markup or script. The result is additionally run through Angular's HTML\n * sanitizer before it reaches the DOM.\n *\n * @example\n * ```html\n * <lc-rich-text-editor\n * [(ngModel)]=\"content\"\n * mode=\"split\"\n * placeholder=\"Write something...\" />\n * ```\n */\n@Component({\n selector: 'lc-rich-text-editor',\n standalone: true,\n imports: [CommonModule],\n templateUrl: './rich-text-editor.component.html',\n styleUrl: './rich-text-editor.component.scss',\n changeDetection: ChangeDetectionStrategy.OnPush,\n providers: [\n {\n provide: NG_VALUE_ACCESSOR,\n useExisting: forwardRef(() => RichTextEditorComponent),\n multi: true,\n },\n ],\n})\nexport class RichTextEditorComponent implements ControlValueAccessor {\n /** Editor mode */\n mode = input<RichTextEditorMode>('rich');\n\n /** Placeholder text */\n placeholder = input<string>('Start typing...');\n\n /** Minimum height in px */\n minHeight = input<number>(200);\n\n /** Maximum height in px (0 = unlimited) */\n maxHeight = input<number>(0);\n\n /** Whether the editor is disabled */\n disabled = input<boolean>(false);\n\n /** Whether the editor is readonly */\n readonly = input<boolean>(false);\n\n /** Toolbar configuration */\n toolbar = input<ToolbarConfig>(DEFAULT_TOOLBAR);\n\n /** Whether to show word count */\n showWordCount = input<boolean>(true);\n\n /** Tooltips and accessible names of the toolbar actions, by action (`{ bold: 'Fett' }`); missing ones keep the English default. */\n actionTitles = input<Partial<Record<ToolbarAction, string>>>({});\n\n /** Label of the rich-text mode button. */\n richModeLabel = input('Rich');\n\n /** Tooltip of the rich-text mode button. */\n richModeTitle = input('Rich Text');\n\n /** Label of the Markdown mode button. */\n markdownModeLabel = input('MD');\n\n /** Tooltip of the Markdown mode button. */\n markdownModeTitle = input('Markdown');\n\n /** Label of the split-view mode button. */\n splitModeLabel = input('Split');\n\n /** Tooltip of the split-view mode button. */\n splitModeTitle = input('Split View');\n\n /** Accessible name of the Markdown text area. */\n markdownEditorAriaLabel = input('Markdown editor');\n\n /** Unit after the word count (`showWordCount`). */\n wordsLabel = input('words');\n\n /** Unit after the character count (`showWordCount`). */\n charactersLabel = input('characters');\n\n /** Emitted on every content change */\n readonly contentChange = output<string>();\n\n private readonly editorArea = viewChild<ElementRef<HTMLTextAreaElement>>('editorArea');\n private readonly richArea = viewChild<ElementRef<HTMLDivElement>>('richArea');\n private readonly sanitizer = inject(DomSanitizer);\n\n /** Internal markdown value */\n protected markdown = signal('');\n\n /** Current active mode: follows the `mode` input until the user toggles it. */\n protected activeMode = linkedSignal<RichTextEditorMode>(() => this.mode());\n\n /** Disabled through the form control (`setDisabledState`), as opposed to the input. */\n private readonly formDisabled = signal(false);\n\n /** Disabled by either route — the one flag the template consults. */\n protected readonly isDisabled = computed(() => this.disabled() || this.formDisabled());\n\n /** Whether the content can currently be edited at all. */\n protected readonly editable = computed(() => !this.isDisabled() && !this.readonly());\n\n /** Word count */\n protected wordCount = computed(() => {\n const text = this.markdown().trim();\n if (!text) return 0;\n return text.split(/\\s+/).length;\n });\n\n /** Character count */\n protected charCount = computed(() => this.markdown().length);\n\n /**\n * Rendered HTML from markdown — escaped by the converter and, on top of that,\n * passed through Angular's HTML sanitizer, so it is safe to assign to\n * `innerHTML` directly.\n */\n protected renderedHtml = computed(() => this.sanitizeHtml(this.markdownToHtml(this.markdown())));\n\n // CVA\n private onChange: (value: string) => void = () => { /* set by registerOnChange */ };\n private onTouched: () => void = () => { /* set by registerOnTouched */ };\n\n constructor() {\n // The rich area lives inside an `@switch`, so it comes and goes with the\n // mode. Whenever it (re)appears, it starts empty and has to be filled from\n // the markdown — including the very first time, which is after any\n // `writeValue` a form control performs before the view exists. Only the\n // element's presence is tracked: re-rendering on every markdown change would\n // wipe the caret while the user types in it.\n effect(() => {\n const el = this.richArea()?.nativeElement;\n if (el) untracked(() => this.renderRich(el));\n });\n }\n\n // -- ControlValueAccessor --\n writeValue(value: string | null | undefined): void {\n this.markdown.set(value || '');\n const el = this.richArea()?.nativeElement;\n if (el) this.renderRich(el);\n }\n\n registerOnChange(fn: (value: string) => void): void {\n this.onChange = fn;\n }\n\n registerOnTouched(fn: () => void): void {\n this.onTouched = fn;\n }\n\n setDisabledState(isDisabled: boolean): void {\n this.formDisabled.set(isDisabled);\n }\n\n // -- Mode switching --\n protected switchMode(mode: RichTextEditorMode): void {\n if (this.activeMode() === 'rich' && mode !== 'rich') {\n // Sync rich content to markdown before the rich area is torn down.\n const el = this.richArea()?.nativeElement;\n if (el) this.markdown.set(this.htmlToMarkdown(el.innerHTML));\n }\n // Entering rich mode: the effect in the constructor renders the markdown\n // into the freshly created rich area.\n this.activeMode.set(mode);\n }\n\n // -- Toolbar actions --\n protected onToolbarAction(action: ToolbarAction): void {\n if (!this.editable()) return;\n\n if (this.activeMode() === 'rich') {\n this.execRichCommand(action);\n } else {\n this.insertMarkdownSyntax(action);\n }\n }\n\n private execRichCommand(action: ToolbarAction): void {\n switch (action) {\n case 'bold':\n document.execCommand('bold');\n break;\n case 'italic':\n document.execCommand('italic');\n break;\n case 'underline':\n document.execCommand('underline');\n break;\n case 'strikethrough':\n document.execCommand('strikeThrough');\n break;\n case 'h1':\n document.execCommand('formatBlock', false, 'h1');\n break;\n case 'h2':\n document.execCommand('formatBlock', false, 'h2');\n break;\n case 'h3':\n document.execCommand('formatBlock', false, 'h3');\n break;\n case 'ul':\n document.execCommand('insertUnorderedList');\n break;\n case 'ol':\n document.execCommand('insertOrderedList');\n break;\n case 'blockquote':\n document.execCommand('formatBlock', false, 'blockquote');\n break;\n case 'code':\n document.execCommand('insertHTML', false, '<code>' + this.getSelection() + '</code>');\n break;\n case 'codeblock':\n document.execCommand('insertHTML', false, '<pre><code>' + this.getSelection() + '</code></pre>');\n break;\n case 'link': {\n const url = prompt('Enter URL:');\n if (url) document.execCommand('createLink', false, url);\n break;\n }\n case 'hr':\n document.execCommand('insertHorizontalRule');\n break;\n }\n this.syncFromRich();\n }\n\n private insertMarkdownSyntax(action: ToolbarAction): void {\n const textarea = this.editorArea()?.nativeElement;\n if (!textarea) return;\n\n const start = textarea.selectionStart;\n const end = textarea.selectionEnd;\n const text = this.markdown();\n const selected = text.substring(start, end);\n\n let insertion = '';\n let cursorOffset = 0;\n\n switch (action) {\n case 'bold':\n insertion = `**${selected || 'bold text'}**`;\n cursorOffset = selected ? insertion.length : 2;\n break;\n case 'italic':\n insertion = `*${selected || 'italic text'}*`;\n cursorOffset = selected ? insertion.length : 1;\n break;\n case 'underline':\n insertion = `<u>${selected || 'underlined text'}</u>`;\n cursorOffset = selected ? insertion.length : 3;\n break;\n case 'strikethrough':\n insertion = `~~${selected || 'strikethrough'}~~`;\n cursorOffset = selected ? insertion.length : 2;\n break;\n case 'h1':\n insertion = `# ${selected || 'Heading 1'}`;\n cursorOffset = insertion.length;\n break;\n case 'h2':\n insertion = `## ${selected || 'Heading 2'}`;\n cursorOffset = insertion.length;\n break;\n case 'h3':\n insertion = `### ${selected || 'Heading 3'}`;\n cursorOffset = insertion.length;\n break;\n case 'ul':\n insertion = `- ${selected || 'List item'}`;\n cursorOffset = insertion.length;\n break;\n case 'ol':\n insertion = `1. ${selected || 'List item'}`;\n cursorOffset = insertion.length;\n break;\n case 'blockquote':\n insertion = `> ${selected || 'Quote'}`;\n cursorOffset = insertion.length;\n break;\n case 'code':\n insertion = `\\`${selected || 'code'}\\``;\n cursorOffset = selected ? insertion.length : 1;\n break;\n case 'codeblock':\n insertion = `\\`\\`\\`\\n${selected || 'code'}\\n\\`\\`\\``;\n cursorOffset = 4;\n break;\n case 'link':\n insertion = `[${selected || 'link text'}](url)`;\n cursorOffset = selected ? insertion.length - 5 : 1;\n break;\n case 'image':\n insertion = ``;\n cursorOffset = selected ? insertion.length - 5 : 2;\n break;\n case 'hr':\n insertion = `\\n---\\n`;\n cursorOffset = insertion.length;\n break;\n }\n\n const newText = text.substring(0, start) + insertion + text.substring(end);\n this.markdown.set(newText);\n this.emitChange(newText);\n\n setTimeout(() => {\n textarea.focus();\n textarea.setSelectionRange(start + cursorOffset, start + cursorOffset);\n });\n }\n\n // -- Content input handlers --\n protected onMarkdownInput(event: Event): void {\n const value = (event.target as HTMLTextAreaElement).value;\n this.markdown.set(value);\n this.emitChange(value);\n }\n\n protected onRichInput(): void {\n this.syncFromRich();\n }\n\n protected onBlur(): void {\n this.onTouched();\n }\n\n private syncFromRich(): void {\n const el = this.richArea()?.nativeElement;\n if (!el) return;\n const md = this.htmlToMarkdown(el.innerHTML);\n this.markdown.set(md);\n this.emitChange(md);\n }\n\n /** Puts the current markdown into the rich area, as sanitised HTML. */\n private renderRich(el: HTMLDivElement): void {\n el.innerHTML = this.renderedHtml();\n }\n\n /**\n * Angular's HTML sanitizer, as the last line of defence behind the escaping\n * `markdownToHtml` does itself: whatever it might miss, this strips.\n */\n private sanitizeHtml(html: string): string {\n return this.sanitizer.sanitize(SecurityContext.HTML, html) ?? '';\n }\n\n private emitChange(value: string): void {\n this.onChange(value);\n this.contentChange.emit(value);\n }\n\n private getSelection(): string {\n return window.getSelection()?.toString() || '';\n }\n\n // -- Toolbar label helpers --\n protected getActionLabel(action: ToolbarAction): string {\n const labels: Record<ToolbarAction, string> = {\n bold: 'B',\n italic: 'I',\n underline: 'U',\n strikethrough: 'S',\n h1: 'H1',\n h2: 'H2',\n h3: 'H3',\n ul: '•',\n ol: '1.',\n blockquote: '\"',\n code: '<>',\n codeblock: '{ }',\n link: '🔗',\n image: '🖼',\n hr: '—',\n };\n return labels[action] || action;\n }\n\n protected getActionTitle(action: ToolbarAction): string {\n const titles: Record<ToolbarAction, string> = {\n bold: 'Bold',\n italic: 'Italic',\n underline: 'Underline',\n strikethrough: 'Strikethrough',\n h1: 'Heading 1',\n h2: 'Heading 2',\n h3: 'Heading 3',\n ul: 'Unordered List',\n ol: 'Ordered List',\n blockquote: 'Blockquote',\n code: 'Inline Code',\n codeblock: 'Code Block',\n link: 'Insert Link',\n image: 'Insert Image',\n hr: 'Horizontal Rule',\n };\n return this.actionTitles()[action] || titles[action] || action;\n }\n\n // -- Markdown <-> HTML conversion (simple built-in) --\n /**\n * Converts the editor's markdown subset to HTML. The source is HTML-escaped\n * *first*, so nothing in it can open a tag or an attribute; the conversions\n * below then only ever add markup of their own. Raw HTML in the markdown is\n * therefore shown as text — with one exception, `<u>`, which the toolbar's\n * underline action emits (markdown has no underline) and which is let back\n * through in escaped form only.\n */\n protected markdownToHtml(md: string): string {\n if (!md) return '';\n\n let html = escapeHtml(md);\n\n // Code blocks (must be first)\n html = html.replace(/```(\\w*)\\n([\\s\\S]*?)```/g, '<pre><code class=\"language-$1\">$2</code></pre>');\n\n // Headings\n html = html.replace(/^### (.+)$/gm, '<h3>$1</h3>');\n html = html.replace(/^## (.+)$/gm, '<h2>$1</h2>');\n html = html.replace(/^# (.+)$/gm, '<h1>$1</h1>');\n\n // Horizontal rule\n html = html.replace(/^---$/gm, '<hr>');\n\n // Bold/Italic\n html = html.replace(/\\*\\*\\*(.+?)\\*\\*\\*/g, '<strong><em>$1</em></strong>');\n html = html.replace(/\\*\\*(.+?)\\*\\*/g, '<strong>$1</strong>');\n html = html.replace(/\\*(.+?)\\*/g, '<em>$1</em>');\n html = html.replace(/~~(.+?)~~/g, '<del>$1</del>');\n\n // Underline: the one raw tag the editor itself writes into the markdown.\n html = html.replace(/<u>(.+?)<\\/u>/g, '<u>$1</u>');\n\n // Inline code\n html = html.replace(/`(.+?)`/g, '<code>$1</code>');\n\n // Links and images. Only safe URLs become attributes; anything else is\n // shown as its text — a `javascript:` link that just isn't a link is far\n // better than one that runs. Quotes are already escaped (see above), so\n // the URL cannot break out of the attribute either.\n html = html.replace(/!\\[(.+?)\\]\\((.+?)\\)/g, (_m, alt: string, src: string) => {\n const url = safeUrl(src, true);\n return url ? `<img alt=\"${alt}\" src=\"${url}\" />` : alt;\n });\n html = html.replace(/\\[(.+?)\\]\\((.+?)\\)/g, (_m, text: string, href: string) => {\n const url = safeUrl(href);\n return url ? `<a href=\"${url}\">${text}</a>` : text;\n });\n\n // Blockquotes — the marker is `>` by now, the source having been escaped.\n html = html.replace(/^> (.+)$/gm, '<blockquote>$1</blockquote>');\n\n // Unordered lists\n html = html.replace(/^- (.+)$/gm, '<li>$1</li>');\n html = html.replace(/(<li>.*<\\/li>\\n?)+/g, '<ul>$&</ul>');\n\n // Ordered lists\n html = html.replace(/^\\d+\\. (.+)$/gm, '<li>$1</li>');\n\n // Paragraphs (lines that aren't already wrapped)\n html = html.replace(/^(?!<[a-z])((?!^\\s*$).+)$/gm, '<p>$1</p>');\n\n // Clean up empty paragraphs\n html = html.replace(/<p>\\s*<\\/p>/g, '');\n\n return html.trim();\n }\n\n private htmlToMarkdown(html: string): string {\n if (!html) return '';\n\n let md = html;\n\n // Block elements\n md = md.replace(/<h1[^>]*>(.*?)<\\/h1>/gi, '# $1\\n');\n md = md.replace(/<h2[^>]*>(.*?)<\\/h2>/gi, '## $1\\n');\n md = md.replace(/<h3[^>]*>(.*?)<\\/h3>/gi, '### $1\\n');\n md = md.replace(/<hr\\s*\\/?>/gi, '---\\n');\n md = md.replace(/<blockquote[^>]*>(.*?)<\\/blockquote>/gi, '> $1\\n');\n md = md.replace(/<pre><code[^>]*>([\\s\\S]*?)<\\/code><\\/pre>/gi, '```\\n$1\\n```\\n');\n\n // Lists\n md = md.replace(/<ul[^>]*>([\\s\\S]*?)<\\/ul>/gi, '$1');\n md = md.replace(/<ol[^>]*>([\\s\\S]*?)<\\/ol>/gi, '$1');\n md = md.replace(/<li[^>]*>(.*?)<\\/li>/gi, '- $1\\n');\n\n // Inline\n md = md.replace(/<strong[^>]*>(.*?)<\\/strong>/gi, '**$1**');\n md = md.replace(/<b[^>]*>(.*?)<\\/b>/gi, '**$1**');\n md = md.replace(/<em[^>]*>(.*?)<\\/em>/gi, '*$1*');\n md = md.replace(/<i[^>]*>(.*?)<\\/i>/gi, '*$1*');\n md = md.replace(/<del[^>]*>(.*?)<\\/del>/gi, '~~$1~~');\n md = md.replace(/<u[^>]*>(.*?)<\\/u>/gi, '<u>$1</u>');\n md = md.replace(/<code[^>]*>(.*?)<\\/code>/gi, '`$1`');\n md = md.replace(/<a[^>]*href=\"([^\"]*)\"[^>]*>(.*?)<\\/a>/gi, '[$2]($1)');\n md = md.replace(/<img[^>]*alt=\"([^\"]*)\"[^>]*src=\"([^\"]*)\"[^>]*\\/?>/gi, '');\n\n // Paragraphs and line breaks\n md = md.replace(/<p[^>]*>(.*?)<\\/p>/gi, '$1\\n\\n');\n md = md.replace(/<br\\s*\\/?>/gi, '\\n');\n md = md.replace(/<div[^>]*>(.*?)<\\/div>/gi, '$1\\n');\n\n // Strip remaining HTML tags\n md = md.replace(/<[^>]+>/g, '');\n\n // Decode HTML entities\n md = md.replace(/&/g, '&');\n md = md.replace(/</g, '<');\n md = md.replace(/>/g, '>');\n md = md.replace(/"/g, '\"');\n md = md.replace(/ /g, ' ');\n\n // Normalize whitespace\n md = md.replace(/\\n{3,}/g, '\\n\\n');\n\n return md.trim();\n }\n}\n","<div class=\"lc-rich-text-editor\" [class.lc-rich-text-editor--disabled]=\"isDisabled()\">\n <!-- Toolbar -->\n <div class=\"lc-rich-text-editor__toolbar\">\n <div class=\"lc-rich-text-editor__toolbar-actions\">\n @for (action of toolbar().actions; track action) {\n <button\n type=\"button\"\n class=\"lc-rich-text-editor__toolbar-btn\"\n [title]=\"getActionTitle(action)\"\n [attr.aria-label]=\"getActionTitle(action)\"\n [disabled]=\"!editable()\"\n (click)=\"onToolbarAction(action)\"\n >\n {{ getActionLabel(action) }}\n </button>\n }\n </div>\n <div class=\"lc-rich-text-editor__toolbar-modes\">\n <button\n type=\"button\"\n class=\"lc-rich-text-editor__mode-btn\"\n [class.active]=\"activeMode() === 'rich'\"\n (click)=\"switchMode('rich')\"\n [attr.title]=\"richModeTitle()\"\n >{{ richModeLabel() }}</button>\n <button\n type=\"button\"\n class=\"lc-rich-text-editor__mode-btn\"\n [class.active]=\"activeMode() === 'markdown'\"\n (click)=\"switchMode('markdown')\"\n [attr.title]=\"markdownModeTitle()\"\n >{{ markdownModeLabel() }}</button>\n <button\n type=\"button\"\n class=\"lc-rich-text-editor__mode-btn\"\n [class.active]=\"activeMode() === 'split'\"\n (click)=\"switchMode('split')\"\n [attr.title]=\"splitModeTitle()\"\n >{{ splitModeLabel() }}</button>\n </div>\n </div>\n\n <!-- Editor area -->\n <div\n class=\"lc-rich-text-editor__content\"\n [style.min-height.px]=\"minHeight()\"\n [style.max-height.px]=\"maxHeight() || null\"\n >\n @switch (activeMode()) {\n @case ('rich') {\n <!-- The rich area is filled from the markdown by the component (see the\n constructor effect); it must never receive markup Angular hasn't\n sanitised. `contenteditable` follows the disabled/readonly state —\n a greyed-out toolbar alone would still let the user type. -->\n <div\n #richArea\n class=\"lc-rich-text-editor__rich\"\n [attr.contenteditable]=\"editable() ? 'true' : 'false'\"\n [attr.aria-disabled]=\"isDisabled() ? 'true' : null\"\n [attr.aria-readonly]=\"readonly() && !isDisabled() ? 'true' : null\"\n [attr.data-placeholder]=\"placeholder()\"\n [class.lc-rich-text-editor__rich--empty]=\"!markdown()\"\n (input)=\"onRichInput()\"\n (blur)=\"onBlur()\"\n role=\"textbox\"\n aria-multiline=\"true\"\n [attr.aria-label]=\"placeholder()\"\n ></div>\n }\n @case ('markdown') {\n <textarea\n #editorArea\n class=\"lc-rich-text-editor__textarea\"\n [placeholder]=\"placeholder()\"\n [value]=\"markdown()\"\n [disabled]=\"isDisabled()\"\n [readOnly]=\"readonly()\"\n (input)=\"onMarkdownInput($event)\"\n (blur)=\"onBlur()\"\n spellcheck=\"false\"\n [attr.aria-label]=\"markdownEditorAriaLabel()\"\n ></textarea>\n }\n @case ('split') {\n <div class=\"lc-rich-text-editor__split\">\n <textarea\n #editorArea\n class=\"lc-rich-text-editor__textarea lc-rich-text-editor__split-editor\"\n [placeholder]=\"placeholder()\"\n [value]=\"markdown()\"\n [disabled]=\"isDisabled()\"\n [readOnly]=\"readonly()\"\n (input)=\"onMarkdownInput($event)\"\n (blur)=\"onBlur()\"\n spellcheck=\"false\"\n [attr.aria-label]=\"markdownEditorAriaLabel()\"\n ></textarea>\n <div\n class=\"lc-rich-text-editor__split-preview\"\n [innerHTML]=\"renderedHtml()\"\n ></div>\n </div>\n }\n }\n </div>\n\n <!-- Footer -->\n @if (showWordCount()) {\n <div class=\"lc-rich-text-editor__footer\">\n <span>{{ wordCount() }} {{ wordsLabel() }}</span>\n <span>{{ charCount() }} {{ charactersLabel() }}</span>\n </div>\n }\n</div>\n"],"mappings":"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"}
|
|
@@ -0,0 +1,415 @@
|
|
|
1
|
+
import * as i0 from "@angular/core";
|
|
2
|
+
import { ChangeDetectionStrategy, Component, computed, input, output, signal } from "@angular/core";
|
|
3
|
+
import { chartColor, formatChartValue, niceScale, toFinite } from "@lifecorner/angular-ui-kit/internal/chart";
|
|
4
|
+
const TOOLTIP_CHAR_W = 6;
|
|
5
|
+
const TOOLTIP_H = 18;
|
|
6
|
+
var ScatterPlotComponent = class ScatterPlotComponent {
|
|
7
|
+
series = input.required(...ngDevMode ? [{ debugName: "series" }] : /* istanbul ignore next */ []);
|
|
8
|
+
width = input(400, ...ngDevMode ? [{ debugName: "width" }] : /* istanbul ignore next */ []);
|
|
9
|
+
height = input(300, ...ngDevMode ? [{ debugName: "height" }] : /* istanbul ignore next */ []);
|
|
10
|
+
showGrid = input(true, ...ngDevMode ? [{ debugName: "showGrid" }] : /* istanbul ignore next */ []);
|
|
11
|
+
showXLabels = input(true, ...ngDevMode ? [{ debugName: "showXLabels" }] : /* istanbul ignore next */ []);
|
|
12
|
+
showYLabels = input(true, ...ngDevMode ? [{ debugName: "showYLabels" }] : /* istanbul ignore next */ []);
|
|
13
|
+
showLegend = input(false, ...ngDevMode ? [{ debugName: "showLegend" }] : /* istanbul ignore next */ []);
|
|
14
|
+
showTooltip = input(true, ...ngDevMode ? [{ debugName: "showTooltip" }] : /* istanbul ignore next */ []);
|
|
15
|
+
dotRadius = input(4, ...ngDevMode ? [{ debugName: "dotRadius" }] : /* istanbul ignore next */ []);
|
|
16
|
+
xAxisLabel = input("", ...ngDevMode ? [{ debugName: "xAxisLabel" }] : /* istanbul ignore next */ []);
|
|
17
|
+
yAxisLabel = input("", ...ngDevMode ? [{ debugName: "yAxisLabel" }] : /* istanbul ignore next */ []);
|
|
18
|
+
interactive = input(true, ...ngDevMode ? [{ debugName: "interactive" }] : /* istanbul ignore next */ []);
|
|
19
|
+
formatValue = input(formatChartValue, ...ngDevMode ? [{ debugName: "formatValue" }] : /* istanbul ignore next */ []);
|
|
20
|
+
ariaLabel = input("", ...ngDevMode ? [{ debugName: "ariaLabel" }] : /* istanbul ignore next */ []);
|
|
21
|
+
pointClick = output();
|
|
22
|
+
hoveredPoint = signal(null, ...ngDevMode ? [{ debugName: "hoveredPoint" }] : /* istanbul ignore next */ []);
|
|
23
|
+
PL = 48;
|
|
24
|
+
PR = 16;
|
|
25
|
+
PT = 16;
|
|
26
|
+
PB = 36;
|
|
27
|
+
viewBox = computed(() => `0 0 ${this.width()} ${this.height()}`, ...ngDevMode ? [{ debugName: "viewBox" }] : /* istanbul ignore next */ []);
|
|
28
|
+
cleanSeries = computed(() => (this.series() ?? []).map((ser) => ({
|
|
29
|
+
...ser,
|
|
30
|
+
data: (ser.data ?? []).map((p) => ({
|
|
31
|
+
...p,
|
|
32
|
+
x: toFinite(p.x),
|
|
33
|
+
y: toFinite(p.y)
|
|
34
|
+
}))
|
|
35
|
+
})), ...ngDevMode ? [{ debugName: "cleanSeries" }] : /* istanbul ignore next */ []);
|
|
36
|
+
allPoints = computed(() => this.cleanSeries().flatMap((s) => s.data), ...ngDevMode ? [{ debugName: "allPoints" }] : /* istanbul ignore next */ []);
|
|
37
|
+
extent(values) {
|
|
38
|
+
if (!values.length) return niceScale(0, 1, 5);
|
|
39
|
+
const min = Math.min(...values);
|
|
40
|
+
const max = Math.max(...values);
|
|
41
|
+
const pad = (max - min) * .05 || .5;
|
|
42
|
+
return niceScale(min - pad, max + pad, 5);
|
|
43
|
+
}
|
|
44
|
+
xScale = computed(() => this.extent(this.allPoints().map((p) => p.x)), ...ngDevMode ? [{ debugName: "xScale" }] : /* istanbul ignore next */ []);
|
|
45
|
+
yScale = computed(() => this.extent(this.allPoints().map((p) => p.y)), ...ngDevMode ? [{ debugName: "yScale" }] : /* istanbul ignore next */ []);
|
|
46
|
+
plotArea = computed(() => ({
|
|
47
|
+
x: this.PL,
|
|
48
|
+
y: this.PT,
|
|
49
|
+
w: this.width() - this.PL - this.PR,
|
|
50
|
+
h: this.height() - this.PT - this.PB
|
|
51
|
+
}), ...ngDevMode ? [{ debugName: "plotArea" }] : /* istanbul ignore next */ []);
|
|
52
|
+
toSx(x) {
|
|
53
|
+
const { min, max } = this.xScale();
|
|
54
|
+
const pa = this.plotArea();
|
|
55
|
+
return pa.x + (x - min) / (max - min || 1) * pa.w;
|
|
56
|
+
}
|
|
57
|
+
toSy(y) {
|
|
58
|
+
const { min, max } = this.yScale();
|
|
59
|
+
const pa = this.plotArea();
|
|
60
|
+
return pa.y + pa.h - (y - min) / (max - min || 1) * pa.h;
|
|
61
|
+
}
|
|
62
|
+
gridLinesX = computed(() => {
|
|
63
|
+
if (!this.showGrid()) return [];
|
|
64
|
+
const fmt = this.formatValue();
|
|
65
|
+
return this.xScale().ticks.map((tick) => ({
|
|
66
|
+
x: this.toSx(tick),
|
|
67
|
+
label: fmt(tick)
|
|
68
|
+
}));
|
|
69
|
+
}, ...ngDevMode ? [{ debugName: "gridLinesX" }] : /* istanbul ignore next */ []);
|
|
70
|
+
gridLinesY = computed(() => {
|
|
71
|
+
if (!this.showGrid()) return [];
|
|
72
|
+
const fmt = this.formatValue();
|
|
73
|
+
return this.yScale().ticks.map((tick) => ({
|
|
74
|
+
y: this.toSy(tick),
|
|
75
|
+
label: fmt(tick)
|
|
76
|
+
}));
|
|
77
|
+
}, ...ngDevMode ? [{ debugName: "gridLinesY" }] : /* istanbul ignore next */ []);
|
|
78
|
+
renderedSeries = computed(() => {
|
|
79
|
+
const dr = this.dotRadius();
|
|
80
|
+
const fmt = this.formatValue();
|
|
81
|
+
return this.cleanSeries().map((ser, si) => {
|
|
82
|
+
const color = ser.color || chartColor(si);
|
|
83
|
+
const points = ser.data.map((p) => {
|
|
84
|
+
const coords = `(${fmt(p.x)}, ${fmt(p.y)})`;
|
|
85
|
+
const label = p.label || coords;
|
|
86
|
+
return {
|
|
87
|
+
cx: this.toSx(p.x),
|
|
88
|
+
cy: this.toSy(p.y),
|
|
89
|
+
r: Math.max(0, toFinite(p.size, dr)),
|
|
90
|
+
label,
|
|
91
|
+
ariaLabel: `${ser.label}: ${p.label ? `${p.label} ${coords}` : coords}`,
|
|
92
|
+
orig: p
|
|
93
|
+
};
|
|
94
|
+
});
|
|
95
|
+
return {
|
|
96
|
+
label: ser.label,
|
|
97
|
+
color,
|
|
98
|
+
points
|
|
99
|
+
};
|
|
100
|
+
});
|
|
101
|
+
}, ...ngDevMode ? [{ debugName: "renderedSeries" }] : /* istanbul ignore next */ []);
|
|
102
|
+
legendItems = computed(() => {
|
|
103
|
+
if (!this.showLegend()) return [];
|
|
104
|
+
return this.renderedSeries().map((s) => ({
|
|
105
|
+
label: s.label,
|
|
106
|
+
color: s.color
|
|
107
|
+
}));
|
|
108
|
+
}, ...ngDevMode ? [{ debugName: "legendItems" }] : /* istanbul ignore next */ []);
|
|
109
|
+
axisLine = computed(() => {
|
|
110
|
+
const pa = this.plotArea();
|
|
111
|
+
return {
|
|
112
|
+
vx1: pa.x,
|
|
113
|
+
vy1: pa.y,
|
|
114
|
+
vx2: pa.x,
|
|
115
|
+
vy2: pa.y + pa.h,
|
|
116
|
+
hx1: pa.x,
|
|
117
|
+
hy1: pa.y + pa.h,
|
|
118
|
+
hx2: pa.x + pa.w,
|
|
119
|
+
hy2: pa.y + pa.h
|
|
120
|
+
};
|
|
121
|
+
}, ...ngDevMode ? [{ debugName: "axisLine" }] : /* istanbul ignore next */ []);
|
|
122
|
+
effectiveAriaLabel = computed(() => {
|
|
123
|
+
const explicit = this.ariaLabel();
|
|
124
|
+
if (explicit) return explicit;
|
|
125
|
+
const series = this.cleanSeries();
|
|
126
|
+
const xl = this.xAxisLabel();
|
|
127
|
+
const yl = this.yAxisLabel();
|
|
128
|
+
const axes = xl || yl ? ` (${xl || "x"} vs ${yl || "y"})` : "";
|
|
129
|
+
if (!series.length) return `Scatter plot${axes}: no data`;
|
|
130
|
+
return `Scatter plot${axes}: ${series.map((s, i) => {
|
|
131
|
+
const n = s.data.length;
|
|
132
|
+
return `${s.label || `Series ${i + 1}`} ${n} ${n === 1 ? "point" : "points"}`;
|
|
133
|
+
}).join(", ")}`;
|
|
134
|
+
}, ...ngDevMode ? [{ debugName: "effectiveAriaLabel" }] : /* istanbul ignore next */ []);
|
|
135
|
+
onDotEnter(cx, cy, label) {
|
|
136
|
+
if (!this.showTooltip()) return;
|
|
137
|
+
const w = label.length * TOOLTIP_CHAR_W + 16;
|
|
138
|
+
const half = w / 2;
|
|
139
|
+
const sx = Math.min(Math.max(cx, half), this.width() - half);
|
|
140
|
+
const above = cy - 12 - TOOLTIP_H;
|
|
141
|
+
this.hoveredPoint.set({
|
|
142
|
+
label,
|
|
143
|
+
sx,
|
|
144
|
+
ty: above < 0 ? cy + 12 : above,
|
|
145
|
+
w
|
|
146
|
+
});
|
|
147
|
+
}
|
|
148
|
+
onDotLeave() {
|
|
149
|
+
this.hoveredPoint.set(null);
|
|
150
|
+
}
|
|
151
|
+
onDotClick(seriesLabel, point) {
|
|
152
|
+
this.pointClick.emit({
|
|
153
|
+
series: seriesLabel,
|
|
154
|
+
point
|
|
155
|
+
});
|
|
156
|
+
}
|
|
157
|
+
tooltipH = TOOLTIP_H;
|
|
158
|
+
static ɵfac = i0.ɵɵngDeclareFactory({
|
|
159
|
+
minVersion: "12.0.0",
|
|
160
|
+
version: "22.2.2",
|
|
161
|
+
ngImport: i0,
|
|
162
|
+
type: ScatterPlotComponent,
|
|
163
|
+
deps: [],
|
|
164
|
+
target: i0.ɵɵFactoryTarget.Component
|
|
165
|
+
});
|
|
166
|
+
static ɵcmp = i0.ɵɵngDeclareComponent({
|
|
167
|
+
minVersion: "17.0.0",
|
|
168
|
+
version: "22.2.2",
|
|
169
|
+
type: ScatterPlotComponent,
|
|
170
|
+
isStandalone: true,
|
|
171
|
+
selector: "lc-scatter-plot",
|
|
172
|
+
inputs: {
|
|
173
|
+
series: {
|
|
174
|
+
classPropertyName: "series",
|
|
175
|
+
publicName: "series",
|
|
176
|
+
isSignal: true,
|
|
177
|
+
isRequired: true,
|
|
178
|
+
transformFunction: null
|
|
179
|
+
},
|
|
180
|
+
width: {
|
|
181
|
+
classPropertyName: "width",
|
|
182
|
+
publicName: "width",
|
|
183
|
+
isSignal: true,
|
|
184
|
+
isRequired: false,
|
|
185
|
+
transformFunction: null
|
|
186
|
+
},
|
|
187
|
+
height: {
|
|
188
|
+
classPropertyName: "height",
|
|
189
|
+
publicName: "height",
|
|
190
|
+
isSignal: true,
|
|
191
|
+
isRequired: false,
|
|
192
|
+
transformFunction: null
|
|
193
|
+
},
|
|
194
|
+
showGrid: {
|
|
195
|
+
classPropertyName: "showGrid",
|
|
196
|
+
publicName: "showGrid",
|
|
197
|
+
isSignal: true,
|
|
198
|
+
isRequired: false,
|
|
199
|
+
transformFunction: null
|
|
200
|
+
},
|
|
201
|
+
showXLabels: {
|
|
202
|
+
classPropertyName: "showXLabels",
|
|
203
|
+
publicName: "showXLabels",
|
|
204
|
+
isSignal: true,
|
|
205
|
+
isRequired: false,
|
|
206
|
+
transformFunction: null
|
|
207
|
+
},
|
|
208
|
+
showYLabels: {
|
|
209
|
+
classPropertyName: "showYLabels",
|
|
210
|
+
publicName: "showYLabels",
|
|
211
|
+
isSignal: true,
|
|
212
|
+
isRequired: false,
|
|
213
|
+
transformFunction: null
|
|
214
|
+
},
|
|
215
|
+
showLegend: {
|
|
216
|
+
classPropertyName: "showLegend",
|
|
217
|
+
publicName: "showLegend",
|
|
218
|
+
isSignal: true,
|
|
219
|
+
isRequired: false,
|
|
220
|
+
transformFunction: null
|
|
221
|
+
},
|
|
222
|
+
showTooltip: {
|
|
223
|
+
classPropertyName: "showTooltip",
|
|
224
|
+
publicName: "showTooltip",
|
|
225
|
+
isSignal: true,
|
|
226
|
+
isRequired: false,
|
|
227
|
+
transformFunction: null
|
|
228
|
+
},
|
|
229
|
+
dotRadius: {
|
|
230
|
+
classPropertyName: "dotRadius",
|
|
231
|
+
publicName: "dotRadius",
|
|
232
|
+
isSignal: true,
|
|
233
|
+
isRequired: false,
|
|
234
|
+
transformFunction: null
|
|
235
|
+
},
|
|
236
|
+
xAxisLabel: {
|
|
237
|
+
classPropertyName: "xAxisLabel",
|
|
238
|
+
publicName: "xAxisLabel",
|
|
239
|
+
isSignal: true,
|
|
240
|
+
isRequired: false,
|
|
241
|
+
transformFunction: null
|
|
242
|
+
},
|
|
243
|
+
yAxisLabel: {
|
|
244
|
+
classPropertyName: "yAxisLabel",
|
|
245
|
+
publicName: "yAxisLabel",
|
|
246
|
+
isSignal: true,
|
|
247
|
+
isRequired: false,
|
|
248
|
+
transformFunction: null
|
|
249
|
+
},
|
|
250
|
+
interactive: {
|
|
251
|
+
classPropertyName: "interactive",
|
|
252
|
+
publicName: "interactive",
|
|
253
|
+
isSignal: true,
|
|
254
|
+
isRequired: false,
|
|
255
|
+
transformFunction: null
|
|
256
|
+
},
|
|
257
|
+
formatValue: {
|
|
258
|
+
classPropertyName: "formatValue",
|
|
259
|
+
publicName: "formatValue",
|
|
260
|
+
isSignal: true,
|
|
261
|
+
isRequired: false,
|
|
262
|
+
transformFunction: null
|
|
263
|
+
},
|
|
264
|
+
ariaLabel: {
|
|
265
|
+
classPropertyName: "ariaLabel",
|
|
266
|
+
publicName: "ariaLabel",
|
|
267
|
+
isSignal: true,
|
|
268
|
+
isRequired: false,
|
|
269
|
+
transformFunction: null
|
|
270
|
+
}
|
|
271
|
+
},
|
|
272
|
+
outputs: { pointClick: "pointClick" },
|
|
273
|
+
ngImport: i0,
|
|
274
|
+
template: "<div class=\"lc-scatter-plot\">\n <svg\n [attr.width]=\"width()\"\n [attr.height]=\"height()\"\n [attr.viewBox]=\"viewBox()\"\n [attr.role]=\"interactive() ? 'group' : 'img'\"\n [attr.aria-label]=\"effectiveAriaLabel()\"\n class=\"lc-scatter-plot__svg\"\n >\n <title>{{ effectiveAriaLabel() }}</title>\n\n <!-- Grid, axes and tick labels are decoration for AT; the summary carries the meaning. -->\n <g aria-hidden=\"true\">\n <!-- Grid lines Y -->\n @for (line of gridLinesY(); track line.y) {\n <line\n [attr.x1]=\"axisLine().hx1\"\n [attr.y1]=\"line.y\"\n [attr.x2]=\"axisLine().hx2\"\n [attr.y2]=\"line.y\"\n class=\"lc-scatter-plot__grid-line\"\n />\n @if (showYLabels()) {\n <text\n [attr.x]=\"axisLine().vx1 - 6\"\n [attr.y]=\"line.y\"\n text-anchor=\"end\"\n dominant-baseline=\"central\"\n class=\"lc-scatter-plot__label\"\n >{{ line.label }}</text>\n }\n }\n\n <!-- Grid lines X -->\n @for (line of gridLinesX(); track line.x) {\n <line\n [attr.x1]=\"line.x\"\n [attr.y1]=\"axisLine().vy1\"\n [attr.x2]=\"line.x\"\n [attr.y2]=\"axisLine().vy2\"\n class=\"lc-scatter-plot__grid-line\"\n />\n @if (showXLabels()) {\n <!-- Tick labels sit just under the plot; the axis title takes the last line of\n the bottom padding, so the two never overlap. -->\n <text\n [attr.x]=\"line.x\"\n [attr.y]=\"plotArea().y + plotArea().h + 14\"\n text-anchor=\"middle\"\n class=\"lc-scatter-plot__label\"\n >{{ line.label }}</text>\n }\n }\n\n <!-- Axes -->\n <line [attr.x1]=\"axisLine().vx1\" [attr.y1]=\"axisLine().vy1\" [attr.x2]=\"axisLine().vx2\" [attr.y2]=\"axisLine().vy2\" class=\"lc-scatter-plot__axis\" />\n <line [attr.x1]=\"axisLine().hx1\" [attr.y1]=\"axisLine().hy1\" [attr.x2]=\"axisLine().hx2\" [attr.y2]=\"axisLine().hy2\" class=\"lc-scatter-plot__axis\" />\n\n <!-- Axis labels -->\n @if (xAxisLabel()) {\n <text [attr.x]=\"plotArea().x + plotArea().w / 2\" [attr.y]=\"height() - 3\" text-anchor=\"middle\" class=\"lc-scatter-plot__axis-label\">{{ xAxisLabel() }}</text>\n }\n @if (yAxisLabel()) {\n <text [attr.x]=\"12\" [attr.y]=\"plotArea().y + plotArea().h / 2\" text-anchor=\"middle\" [attr.transform]=\"'rotate(-90, 12, ' + (plotArea().y + plotArea().h / 2) + ')'\" class=\"lc-scatter-plot__axis-label\">{{ yAxisLabel() }}</text>\n }\n </g>\n\n <!-- Series dots -->\n @for (ser of renderedSeries(); track $index) {\n @for (pt of ser.points; track $index) {\n <circle\n [attr.cx]=\"pt.cx\"\n [attr.cy]=\"pt.cy\"\n [attr.r]=\"pt.r\"\n [attr.fill]=\"ser.color\"\n class=\"lc-scatter-plot__dot\"\n [class.lc-scatter-plot__dot--interactive]=\"interactive()\"\n [attr.tabindex]=\"interactive() ? 0 : null\"\n [attr.role]=\"interactive() ? 'button' : null\"\n [attr.aria-label]=\"interactive() ? pt.ariaLabel : null\"\n (mouseenter)=\"onDotEnter(pt.cx, pt.cy, pt.label)\"\n (mouseleave)=\"onDotLeave()\"\n (focus)=\"onDotEnter(pt.cx, pt.cy, pt.label)\"\n (blur)=\"onDotLeave()\"\n (click)=\"onDotClick(ser.label, pt.orig)\"\n (keydown.enter)=\"onDotClick(ser.label, pt.orig)\"\n (keydown.space)=\"$event.preventDefault(); onDotClick(ser.label, pt.orig)\"\n />\n }\n }\n\n <!-- Tooltip -->\n @if (hoveredPoint(); as hp) {\n <g class=\"lc-scatter-plot__tooltip\" aria-hidden=\"true\">\n <rect\n [attr.x]=\"hp.sx - hp.w / 2\"\n [attr.y]=\"hp.ty\"\n [attr.width]=\"hp.w\"\n [attr.height]=\"tooltipH\"\n rx=\"4\"\n class=\"lc-scatter-plot__tooltip-bg\"\n />\n <text\n [attr.x]=\"hp.sx\"\n [attr.y]=\"hp.ty + tooltipH / 2\"\n text-anchor=\"middle\"\n dominant-baseline=\"central\"\n class=\"lc-scatter-plot__tooltip-text\"\n >{{ hp.label }}</text>\n </g>\n }\n </svg>\n\n @if (legendItems().length) {\n <div class=\"lc-scatter-plot__legend\">\n @for (item of legendItems(); track $index) {\n <div class=\"lc-scatter-plot__legend-item\">\n <span class=\"lc-scatter-plot__legend-dot\" [style.background-color]=\"item.color\"></span>\n <span class=\"lc-scatter-plot__legend-label\">{{ item.label }}</span>\n </div>\n }\n </div>\n }\n</div>\n",
|
|
275
|
+
styles: [".lc-scatter-plot{display:inline-flex;flex-direction:column;align-items:center;gap:.5rem}.lc-scatter-plot__svg{overflow:visible}.lc-scatter-plot__axis{stroke:var(--color-border);stroke-width:1}.lc-scatter-plot__grid-line{stroke:var(--color-border);stroke-width:1;stroke-dasharray:3 3}.lc-scatter-plot__label{font-size:.625rem;fill:var(--color-text-tertiary)}.lc-scatter-plot__axis-label{font-size:.6875rem;fill:var(--color-text-secondary);font-weight:500}.lc-scatter-plot__dot{opacity:.8;transition:opacity .15s,r .15s}.lc-scatter-plot__dot--interactive{cursor:pointer}.lc-scatter-plot__dot:hover{opacity:1;r:6}.lc-scatter-plot__dot:focus-visible{outline:none;opacity:1;stroke:var(--color-text-primary);stroke-width:2}.lc-scatter-plot__tooltip{pointer-events:none}.lc-scatter-plot__tooltip-bg{fill:var(--color-surface-raised);stroke:var(--color-border-strong);stroke-width:1}.lc-scatter-plot__tooltip-text{font-size:.625rem;fill:var(--color-text-primary)}.lc-scatter-plot__legend{display:flex;flex-wrap:wrap;gap:.5rem 1rem;justify-content:center}.lc-scatter-plot__legend-item{display:flex;align-items:center;gap:.375rem;font-size:var(--typography-font-size-sm, .875rem)}.lc-scatter-plot__legend-dot{width:8px;height:8px;border-radius:50%;flex-shrink:0}.lc-scatter-plot__legend-label{color:var(--color-text-secondary)}\n"],
|
|
276
|
+
changeDetection: i0.ChangeDetectionStrategy.OnPush
|
|
277
|
+
});
|
|
278
|
+
};
|
|
279
|
+
i0.ɵɵngDeclareClassMetadata({
|
|
280
|
+
minVersion: "12.0.0",
|
|
281
|
+
version: "22.2.2",
|
|
282
|
+
ngImport: i0,
|
|
283
|
+
type: ScatterPlotComponent,
|
|
284
|
+
decorators: [{
|
|
285
|
+
type: Component,
|
|
286
|
+
args: [{
|
|
287
|
+
selector: "lc-scatter-plot",
|
|
288
|
+
standalone: true,
|
|
289
|
+
changeDetection: ChangeDetectionStrategy.OnPush,
|
|
290
|
+
template: "<div class=\"lc-scatter-plot\">\n <svg\n [attr.width]=\"width()\"\n [attr.height]=\"height()\"\n [attr.viewBox]=\"viewBox()\"\n [attr.role]=\"interactive() ? 'group' : 'img'\"\n [attr.aria-label]=\"effectiveAriaLabel()\"\n class=\"lc-scatter-plot__svg\"\n >\n <title>{{ effectiveAriaLabel() }}</title>\n\n <!-- Grid, axes and tick labels are decoration for AT; the summary carries the meaning. -->\n <g aria-hidden=\"true\">\n <!-- Grid lines Y -->\n @for (line of gridLinesY(); track line.y) {\n <line\n [attr.x1]=\"axisLine().hx1\"\n [attr.y1]=\"line.y\"\n [attr.x2]=\"axisLine().hx2\"\n [attr.y2]=\"line.y\"\n class=\"lc-scatter-plot__grid-line\"\n />\n @if (showYLabels()) {\n <text\n [attr.x]=\"axisLine().vx1 - 6\"\n [attr.y]=\"line.y\"\n text-anchor=\"end\"\n dominant-baseline=\"central\"\n class=\"lc-scatter-plot__label\"\n >{{ line.label }}</text>\n }\n }\n\n <!-- Grid lines X -->\n @for (line of gridLinesX(); track line.x) {\n <line\n [attr.x1]=\"line.x\"\n [attr.y1]=\"axisLine().vy1\"\n [attr.x2]=\"line.x\"\n [attr.y2]=\"axisLine().vy2\"\n class=\"lc-scatter-plot__grid-line\"\n />\n @if (showXLabels()) {\n <!-- Tick labels sit just under the plot; the axis title takes the last line of\n the bottom padding, so the two never overlap. -->\n <text\n [attr.x]=\"line.x\"\n [attr.y]=\"plotArea().y + plotArea().h + 14\"\n text-anchor=\"middle\"\n class=\"lc-scatter-plot__label\"\n >{{ line.label }}</text>\n }\n }\n\n <!-- Axes -->\n <line [attr.x1]=\"axisLine().vx1\" [attr.y1]=\"axisLine().vy1\" [attr.x2]=\"axisLine().vx2\" [attr.y2]=\"axisLine().vy2\" class=\"lc-scatter-plot__axis\" />\n <line [attr.x1]=\"axisLine().hx1\" [attr.y1]=\"axisLine().hy1\" [attr.x2]=\"axisLine().hx2\" [attr.y2]=\"axisLine().hy2\" class=\"lc-scatter-plot__axis\" />\n\n <!-- Axis labels -->\n @if (xAxisLabel()) {\n <text [attr.x]=\"plotArea().x + plotArea().w / 2\" [attr.y]=\"height() - 3\" text-anchor=\"middle\" class=\"lc-scatter-plot__axis-label\">{{ xAxisLabel() }}</text>\n }\n @if (yAxisLabel()) {\n <text [attr.x]=\"12\" [attr.y]=\"plotArea().y + plotArea().h / 2\" text-anchor=\"middle\" [attr.transform]=\"'rotate(-90, 12, ' + (plotArea().y + plotArea().h / 2) + ')'\" class=\"lc-scatter-plot__axis-label\">{{ yAxisLabel() }}</text>\n }\n </g>\n\n <!-- Series dots -->\n @for (ser of renderedSeries(); track $index) {\n @for (pt of ser.points; track $index) {\n <circle\n [attr.cx]=\"pt.cx\"\n [attr.cy]=\"pt.cy\"\n [attr.r]=\"pt.r\"\n [attr.fill]=\"ser.color\"\n class=\"lc-scatter-plot__dot\"\n [class.lc-scatter-plot__dot--interactive]=\"interactive()\"\n [attr.tabindex]=\"interactive() ? 0 : null\"\n [attr.role]=\"interactive() ? 'button' : null\"\n [attr.aria-label]=\"interactive() ? pt.ariaLabel : null\"\n (mouseenter)=\"onDotEnter(pt.cx, pt.cy, pt.label)\"\n (mouseleave)=\"onDotLeave()\"\n (focus)=\"onDotEnter(pt.cx, pt.cy, pt.label)\"\n (blur)=\"onDotLeave()\"\n (click)=\"onDotClick(ser.label, pt.orig)\"\n (keydown.enter)=\"onDotClick(ser.label, pt.orig)\"\n (keydown.space)=\"$event.preventDefault(); onDotClick(ser.label, pt.orig)\"\n />\n }\n }\n\n <!-- Tooltip -->\n @if (hoveredPoint(); as hp) {\n <g class=\"lc-scatter-plot__tooltip\" aria-hidden=\"true\">\n <rect\n [attr.x]=\"hp.sx - hp.w / 2\"\n [attr.y]=\"hp.ty\"\n [attr.width]=\"hp.w\"\n [attr.height]=\"tooltipH\"\n rx=\"4\"\n class=\"lc-scatter-plot__tooltip-bg\"\n />\n <text\n [attr.x]=\"hp.sx\"\n [attr.y]=\"hp.ty + tooltipH / 2\"\n text-anchor=\"middle\"\n dominant-baseline=\"central\"\n class=\"lc-scatter-plot__tooltip-text\"\n >{{ hp.label }}</text>\n </g>\n }\n </svg>\n\n @if (legendItems().length) {\n <div class=\"lc-scatter-plot__legend\">\n @for (item of legendItems(); track $index) {\n <div class=\"lc-scatter-plot__legend-item\">\n <span class=\"lc-scatter-plot__legend-dot\" [style.background-color]=\"item.color\"></span>\n <span class=\"lc-scatter-plot__legend-label\">{{ item.label }}</span>\n </div>\n }\n </div>\n }\n</div>\n",
|
|
291
|
+
styles: [".lc-scatter-plot{display:inline-flex;flex-direction:column;align-items:center;gap:.5rem}.lc-scatter-plot__svg{overflow:visible}.lc-scatter-plot__axis{stroke:var(--color-border);stroke-width:1}.lc-scatter-plot__grid-line{stroke:var(--color-border);stroke-width:1;stroke-dasharray:3 3}.lc-scatter-plot__label{font-size:.625rem;fill:var(--color-text-tertiary)}.lc-scatter-plot__axis-label{font-size:.6875rem;fill:var(--color-text-secondary);font-weight:500}.lc-scatter-plot__dot{opacity:.8;transition:opacity .15s,r .15s}.lc-scatter-plot__dot--interactive{cursor:pointer}.lc-scatter-plot__dot:hover{opacity:1;r:6}.lc-scatter-plot__dot:focus-visible{outline:none;opacity:1;stroke:var(--color-text-primary);stroke-width:2}.lc-scatter-plot__tooltip{pointer-events:none}.lc-scatter-plot__tooltip-bg{fill:var(--color-surface-raised);stroke:var(--color-border-strong);stroke-width:1}.lc-scatter-plot__tooltip-text{font-size:.625rem;fill:var(--color-text-primary)}.lc-scatter-plot__legend{display:flex;flex-wrap:wrap;gap:.5rem 1rem;justify-content:center}.lc-scatter-plot__legend-item{display:flex;align-items:center;gap:.375rem;font-size:var(--typography-font-size-sm, .875rem)}.lc-scatter-plot__legend-dot{width:8px;height:8px;border-radius:50%;flex-shrink:0}.lc-scatter-plot__legend-label{color:var(--color-text-secondary)}\n"]
|
|
292
|
+
}]
|
|
293
|
+
}],
|
|
294
|
+
propDecorators: {
|
|
295
|
+
series: [{
|
|
296
|
+
type: i0.Input,
|
|
297
|
+
args: [{
|
|
298
|
+
isSignal: true,
|
|
299
|
+
alias: "series",
|
|
300
|
+
required: true
|
|
301
|
+
}]
|
|
302
|
+
}],
|
|
303
|
+
width: [{
|
|
304
|
+
type: i0.Input,
|
|
305
|
+
args: [{
|
|
306
|
+
isSignal: true,
|
|
307
|
+
alias: "width",
|
|
308
|
+
required: false
|
|
309
|
+
}]
|
|
310
|
+
}],
|
|
311
|
+
height: [{
|
|
312
|
+
type: i0.Input,
|
|
313
|
+
args: [{
|
|
314
|
+
isSignal: true,
|
|
315
|
+
alias: "height",
|
|
316
|
+
required: false
|
|
317
|
+
}]
|
|
318
|
+
}],
|
|
319
|
+
showGrid: [{
|
|
320
|
+
type: i0.Input,
|
|
321
|
+
args: [{
|
|
322
|
+
isSignal: true,
|
|
323
|
+
alias: "showGrid",
|
|
324
|
+
required: false
|
|
325
|
+
}]
|
|
326
|
+
}],
|
|
327
|
+
showXLabels: [{
|
|
328
|
+
type: i0.Input,
|
|
329
|
+
args: [{
|
|
330
|
+
isSignal: true,
|
|
331
|
+
alias: "showXLabels",
|
|
332
|
+
required: false
|
|
333
|
+
}]
|
|
334
|
+
}],
|
|
335
|
+
showYLabels: [{
|
|
336
|
+
type: i0.Input,
|
|
337
|
+
args: [{
|
|
338
|
+
isSignal: true,
|
|
339
|
+
alias: "showYLabels",
|
|
340
|
+
required: false
|
|
341
|
+
}]
|
|
342
|
+
}],
|
|
343
|
+
showLegend: [{
|
|
344
|
+
type: i0.Input,
|
|
345
|
+
args: [{
|
|
346
|
+
isSignal: true,
|
|
347
|
+
alias: "showLegend",
|
|
348
|
+
required: false
|
|
349
|
+
}]
|
|
350
|
+
}],
|
|
351
|
+
showTooltip: [{
|
|
352
|
+
type: i0.Input,
|
|
353
|
+
args: [{
|
|
354
|
+
isSignal: true,
|
|
355
|
+
alias: "showTooltip",
|
|
356
|
+
required: false
|
|
357
|
+
}]
|
|
358
|
+
}],
|
|
359
|
+
dotRadius: [{
|
|
360
|
+
type: i0.Input,
|
|
361
|
+
args: [{
|
|
362
|
+
isSignal: true,
|
|
363
|
+
alias: "dotRadius",
|
|
364
|
+
required: false
|
|
365
|
+
}]
|
|
366
|
+
}],
|
|
367
|
+
xAxisLabel: [{
|
|
368
|
+
type: i0.Input,
|
|
369
|
+
args: [{
|
|
370
|
+
isSignal: true,
|
|
371
|
+
alias: "xAxisLabel",
|
|
372
|
+
required: false
|
|
373
|
+
}]
|
|
374
|
+
}],
|
|
375
|
+
yAxisLabel: [{
|
|
376
|
+
type: i0.Input,
|
|
377
|
+
args: [{
|
|
378
|
+
isSignal: true,
|
|
379
|
+
alias: "yAxisLabel",
|
|
380
|
+
required: false
|
|
381
|
+
}]
|
|
382
|
+
}],
|
|
383
|
+
interactive: [{
|
|
384
|
+
type: i0.Input,
|
|
385
|
+
args: [{
|
|
386
|
+
isSignal: true,
|
|
387
|
+
alias: "interactive",
|
|
388
|
+
required: false
|
|
389
|
+
}]
|
|
390
|
+
}],
|
|
391
|
+
formatValue: [{
|
|
392
|
+
type: i0.Input,
|
|
393
|
+
args: [{
|
|
394
|
+
isSignal: true,
|
|
395
|
+
alias: "formatValue",
|
|
396
|
+
required: false
|
|
397
|
+
}]
|
|
398
|
+
}],
|
|
399
|
+
ariaLabel: [{
|
|
400
|
+
type: i0.Input,
|
|
401
|
+
args: [{
|
|
402
|
+
isSignal: true,
|
|
403
|
+
alias: "ariaLabel",
|
|
404
|
+
required: false
|
|
405
|
+
}]
|
|
406
|
+
}],
|
|
407
|
+
pointClick: [{
|
|
408
|
+
type: i0.Output,
|
|
409
|
+
args: ["pointClick"]
|
|
410
|
+
}]
|
|
411
|
+
}
|
|
412
|
+
});
|
|
413
|
+
export { ScatterPlotComponent };
|
|
414
|
+
|
|
415
|
+
//# sourceMappingURL=lifecorner-angular-ui-kit-scatter-plot.mjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"lifecorner-angular-ui-kit-scatter-plot.mjs","names":[],"sources":["../../../../libs/angular-ui-kit/src/lib/scatter-plot/scatter-plot.component.ts","../../../../libs/angular-ui-kit/src/lib/scatter-plot/scatter-plot.component.html"],"sourcesContent":["import {\n ChangeDetectionStrategy,\n Component,\n input,\n computed,\n signal,\n output,\n} from '@angular/core';\nimport { chartColor } from '@lifecorner/angular-ui-kit/internal/chart';\nimport {\n ChartValueFormatter,\n formatChartValue,\n niceScale,\n toFinite,\n} from '@lifecorner/angular-ui-kit/internal/chart';\n\nexport interface ScatterPoint {\n x: number;\n y: number;\n label?: string;\n size?: number;\n}\n\nexport interface ScatterSeries {\n label: string;\n data: ScatterPoint[];\n color?: string;\n}\n\n/** Approximate glyph width of the 10px tooltip font, used to size its backplate. */\nconst TOOLTIP_CHAR_W = 6;\nconst TOOLTIP_PAD_X = 8;\nconst TOOLTIP_H = 18;\n\n@Component({\n selector: 'lc-scatter-plot',\n standalone: true,\n templateUrl: './scatter-plot.component.html',\n styleUrls: ['./scatter-plot.component.scss'],\n changeDetection: ChangeDetectionStrategy.OnPush,\n})\n/**\n * Scatter plot for visualizing correlations between two variables.\n *\n * Features:\n * - Multiple data series with automatic color assignment\n * - Variable dot sizes for bubble-chart style (`size` on data points)\n * - Configurable axis labels (X / Y) and grid on a nice tick scale\n * - Interactive dots: hover/focus tooltip, click and Enter/Space emit `pointClick`\n * - Optional legend for multi-series data\n *\n * @example\n * ```html\n * <lc-scatter-plot [series]=\"data\" xAxisLabel=\"Weight\" yAxisLabel=\"Height\" (pointClick)=\"select($event)\" />\n * ```\n */\nexport class ScatterPlotComponent {\n readonly series = input.required<ScatterSeries[]>();\n /** Chart width in pixels (fixed; the SVG is not fluid). */\n readonly width = input(400);\n /** Chart height in pixels. */\n readonly height = input(300);\n readonly showGrid = input(true);\n readonly showXLabels = input(true);\n readonly showYLabels = input(true);\n readonly showLegend = input(false);\n readonly showTooltip = input(true);\n readonly dotRadius = input(4);\n readonly xAxisLabel = input('');\n readonly yAxisLabel = input('');\n /**\n * Whether the dots are interactive: keyboard-focusable buttons that show\n * the tooltip on focus and emit `pointClick` on click / Enter / Space. When\n * false the chart is a static image (`role=\"img\"`).\n */\n readonly interactive = input(true);\n /** Formats axis ticks and the default point label. Defaults to a float-safe `String(value)`. */\n readonly formatValue = input<ChartValueFormatter>(formatChartValue);\n /**\n * Accessible name of the chart. Defaults to a generated summary naming the\n * axes and each series with its point count.\n */\n readonly ariaLabel = input<string>('');\n\n readonly pointClick = output<{ series: string; point: ScatterPoint }>();\n\n /** Tooltip: label, backplate centre x / top y and width (SVG units). */\n protected hoveredPoint = signal<{ label: string; sx: number; ty: number; w: number } | null>(null);\n\n private readonly PL = 48;\n private readonly PR = 16;\n private readonly PT = 16;\n private readonly PB = 36;\n\n protected readonly viewBox = computed(() => `0 0 ${this.width()} ${this.height()}`);\n\n private readonly cleanSeries = computed(() =>\n (this.series() ?? []).map((ser) => ({\n ...ser,\n data: (ser.data ?? []).map((p) => ({ ...p, x: toFinite(p.x), y: toFinite(p.y) })),\n }))\n );\n\n private readonly allPoints = computed(() => this.cleanSeries().flatMap(s => s.data));\n\n /** Nice tick scale over the data extent, padded 5% so edge points don't sit on the axis. */\n private extent(values: number[]) {\n if (!values.length) return niceScale(0, 1, 5);\n const min = Math.min(...values);\n const max = Math.max(...values);\n const pad = (max - min) * 0.05 || 0.5;\n return niceScale(min - pad, max + pad, 5);\n }\n\n private readonly xScale = computed(() => this.extent(this.allPoints().map(p => p.x)));\n private readonly yScale = computed(() => this.extent(this.allPoints().map(p => p.y)));\n\n protected readonly plotArea = computed(() => ({\n x: this.PL,\n y: this.PT,\n w: this.width() - this.PL - this.PR,\n h: this.height() - this.PT - this.PB,\n }));\n\n private toSx(x: number): number {\n const { min, max } = this.xScale();\n const pa = this.plotArea();\n return pa.x + ((x - min) / (max - min || 1)) * pa.w;\n }\n\n private toSy(y: number): number {\n const { min, max } = this.yScale();\n const pa = this.plotArea();\n return pa.y + pa.h - ((y - min) / (max - min || 1)) * pa.h;\n }\n\n protected readonly gridLinesX = computed(() => {\n if (!this.showGrid()) return [];\n const fmt = this.formatValue();\n return this.xScale().ticks.map((tick) => ({ x: this.toSx(tick), label: fmt(tick) }));\n });\n\n protected readonly gridLinesY = computed(() => {\n if (!this.showGrid()) return [];\n const fmt = this.formatValue();\n return this.yScale().ticks.map((tick) => ({ y: this.toSy(tick), label: fmt(tick) }));\n });\n\n protected readonly renderedSeries = computed(() => {\n const dr = this.dotRadius();\n const fmt = this.formatValue();\n\n return this.cleanSeries().map((ser, si) => {\n const color = ser.color || chartColor(si);\n const points = ser.data.map(p => {\n const coords = `(${fmt(p.x)}, ${fmt(p.y)})`;\n const label = p.label || coords;\n return {\n cx: this.toSx(p.x),\n cy: this.toSy(p.y),\n r: Math.max(0, toFinite(p.size, dr)),\n label,\n ariaLabel: `${ser.label}: ${p.label ? `${p.label} ${coords}` : coords}`,\n orig: p,\n };\n });\n return { label: ser.label, color, points };\n });\n });\n\n protected readonly legendItems = computed(() => {\n if (!this.showLegend()) return [];\n return this.renderedSeries().map(s => ({ label: s.label, color: s.color }));\n });\n\n protected readonly axisLine = computed(() => {\n const pa = this.plotArea();\n return {\n vx1: pa.x, vy1: pa.y, vx2: pa.x, vy2: pa.y + pa.h,\n hx1: pa.x, hy1: pa.y + pa.h, hx2: pa.x + pa.w, hy2: pa.y + pa.h,\n };\n });\n\n protected readonly effectiveAriaLabel = computed(() => {\n const explicit = this.ariaLabel();\n if (explicit) return explicit;\n const series = this.cleanSeries();\n const xl = this.xAxisLabel();\n const yl = this.yAxisLabel();\n const axes = xl || yl ? ` (${xl || 'x'} vs ${yl || 'y'})` : '';\n if (!series.length) return `Scatter plot${axes}: no data`;\n const parts = series.map((s, i) => {\n const n = s.data.length;\n return `${s.label || `Series ${i + 1}`} ${n} ${n === 1 ? 'point' : 'points'}`;\n });\n return `Scatter plot${axes}: ${parts.join(', ')}`;\n });\n\n protected onDotEnter(cx: number, cy: number, label: string): void {\n if (!this.showTooltip()) return;\n // Size the backplate from the label and keep it inside the SVG: clamped\n // horizontally, flipped below the dot when there is no room above it.\n const w = label.length * TOOLTIP_CHAR_W + TOOLTIP_PAD_X * 2;\n const half = w / 2;\n const sx = Math.min(Math.max(cx, half), this.width() - half);\n const above = cy - 12 - TOOLTIP_H;\n this.hoveredPoint.set({ label, sx, ty: above < 0 ? cy + 12 : above, w });\n }\n\n protected onDotLeave(): void {\n this.hoveredPoint.set(null);\n }\n\n protected onDotClick(seriesLabel: string, point: ScatterPoint): void {\n this.pointClick.emit({ series: seriesLabel, point });\n }\n\n protected readonly tooltipH = TOOLTIP_H;\n}\n","<div class=\"lc-scatter-plot\">\n <svg\n [attr.width]=\"width()\"\n [attr.height]=\"height()\"\n [attr.viewBox]=\"viewBox()\"\n [attr.role]=\"interactive() ? 'group' : 'img'\"\n [attr.aria-label]=\"effectiveAriaLabel()\"\n class=\"lc-scatter-plot__svg\"\n >\n <title>{{ effectiveAriaLabel() }}</title>\n\n <!-- Grid, axes and tick labels are decoration for AT; the summary carries the meaning. -->\n <g aria-hidden=\"true\">\n <!-- Grid lines Y -->\n @for (line of gridLinesY(); track line.y) {\n <line\n [attr.x1]=\"axisLine().hx1\"\n [attr.y1]=\"line.y\"\n [attr.x2]=\"axisLine().hx2\"\n [attr.y2]=\"line.y\"\n class=\"lc-scatter-plot__grid-line\"\n />\n @if (showYLabels()) {\n <text\n [attr.x]=\"axisLine().vx1 - 6\"\n [attr.y]=\"line.y\"\n text-anchor=\"end\"\n dominant-baseline=\"central\"\n class=\"lc-scatter-plot__label\"\n >{{ line.label }}</text>\n }\n }\n\n <!-- Grid lines X -->\n @for (line of gridLinesX(); track line.x) {\n <line\n [attr.x1]=\"line.x\"\n [attr.y1]=\"axisLine().vy1\"\n [attr.x2]=\"line.x\"\n [attr.y2]=\"axisLine().vy2\"\n class=\"lc-scatter-plot__grid-line\"\n />\n @if (showXLabels()) {\n <!-- Tick labels sit just under the plot; the axis title takes the last line of\n the bottom padding, so the two never overlap. -->\n <text\n [attr.x]=\"line.x\"\n [attr.y]=\"plotArea().y + plotArea().h + 14\"\n text-anchor=\"middle\"\n class=\"lc-scatter-plot__label\"\n >{{ line.label }}</text>\n }\n }\n\n <!-- Axes -->\n <line [attr.x1]=\"axisLine().vx1\" [attr.y1]=\"axisLine().vy1\" [attr.x2]=\"axisLine().vx2\" [attr.y2]=\"axisLine().vy2\" class=\"lc-scatter-plot__axis\" />\n <line [attr.x1]=\"axisLine().hx1\" [attr.y1]=\"axisLine().hy1\" [attr.x2]=\"axisLine().hx2\" [attr.y2]=\"axisLine().hy2\" class=\"lc-scatter-plot__axis\" />\n\n <!-- Axis labels -->\n @if (xAxisLabel()) {\n <text [attr.x]=\"plotArea().x + plotArea().w / 2\" [attr.y]=\"height() - 3\" text-anchor=\"middle\" class=\"lc-scatter-plot__axis-label\">{{ xAxisLabel() }}</text>\n }\n @if (yAxisLabel()) {\n <text [attr.x]=\"12\" [attr.y]=\"plotArea().y + plotArea().h / 2\" text-anchor=\"middle\" [attr.transform]=\"'rotate(-90, 12, ' + (plotArea().y + plotArea().h / 2) + ')'\" class=\"lc-scatter-plot__axis-label\">{{ yAxisLabel() }}</text>\n }\n </g>\n\n <!-- Series dots -->\n @for (ser of renderedSeries(); track $index) {\n @for (pt of ser.points; track $index) {\n <circle\n [attr.cx]=\"pt.cx\"\n [attr.cy]=\"pt.cy\"\n [attr.r]=\"pt.r\"\n [attr.fill]=\"ser.color\"\n class=\"lc-scatter-plot__dot\"\n [class.lc-scatter-plot__dot--interactive]=\"interactive()\"\n [attr.tabindex]=\"interactive() ? 0 : null\"\n [attr.role]=\"interactive() ? 'button' : null\"\n [attr.aria-label]=\"interactive() ? pt.ariaLabel : null\"\n (mouseenter)=\"onDotEnter(pt.cx, pt.cy, pt.label)\"\n (mouseleave)=\"onDotLeave()\"\n (focus)=\"onDotEnter(pt.cx, pt.cy, pt.label)\"\n (blur)=\"onDotLeave()\"\n (click)=\"onDotClick(ser.label, pt.orig)\"\n (keydown.enter)=\"onDotClick(ser.label, pt.orig)\"\n (keydown.space)=\"$event.preventDefault(); onDotClick(ser.label, pt.orig)\"\n />\n }\n }\n\n <!-- Tooltip -->\n @if (hoveredPoint(); as hp) {\n <g class=\"lc-scatter-plot__tooltip\" aria-hidden=\"true\">\n <rect\n [attr.x]=\"hp.sx - hp.w / 2\"\n [attr.y]=\"hp.ty\"\n [attr.width]=\"hp.w\"\n [attr.height]=\"tooltipH\"\n rx=\"4\"\n class=\"lc-scatter-plot__tooltip-bg\"\n />\n <text\n [attr.x]=\"hp.sx\"\n [attr.y]=\"hp.ty + tooltipH / 2\"\n text-anchor=\"middle\"\n dominant-baseline=\"central\"\n class=\"lc-scatter-plot__tooltip-text\"\n >{{ hp.label }}</text>\n </g>\n }\n </svg>\n\n @if (legendItems().length) {\n <div class=\"lc-scatter-plot__legend\">\n @for (item of legendItems(); track $index) {\n <div class=\"lc-scatter-plot__legend-item\">\n <span class=\"lc-scatter-plot__legend-dot\" [style.background-color]=\"item.color\"></span>\n <span class=\"lc-scatter-plot__legend-label\">{{ item.label }}</span>\n </div>\n }\n </div>\n }\n</div>\n"],"mappings":"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"}
|