@rt-tools/ui-kit-v2 0.17.0 → 0.18.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +18 -0
- package/fesm2022/rt-tools-ui-kit-v2-accordion.mjs +79 -0
- package/fesm2022/rt-tools-ui-kit-v2-accordion.mjs.map +1 -0
- package/fesm2022/rt-tools-ui-kit-v2-action-bar.mjs +227 -0
- package/fesm2022/rt-tools-ui-kit-v2-action-bar.mjs.map +1 -0
- package/fesm2022/rt-tools-ui-kit-v2-aside-section.mjs +47 -0
- package/fesm2022/rt-tools-ui-kit-v2-aside-section.mjs.map +1 -0
- package/fesm2022/rt-tools-ui-kit-v2-aside.mjs +702 -0
- package/fesm2022/rt-tools-ui-kit-v2-aside.mjs.map +1 -0
- package/fesm2022/rt-tools-ui-kit-v2-autocomplete.mjs +214 -0
- package/fesm2022/rt-tools-ui-kit-v2-autocomplete.mjs.map +1 -0
- package/fesm2022/rt-tools-ui-kit-v2-bar-list.mjs +53 -0
- package/fesm2022/rt-tools-ui-kit-v2-bar-list.mjs.map +1 -0
- package/fesm2022/rt-tools-ui-kit-v2-bottom-sheet.mjs +88 -0
- package/fesm2022/rt-tools-ui-kit-v2-bottom-sheet.mjs.map +1 -0
- package/fesm2022/rt-tools-ui-kit-v2-button.mjs +365 -0
- package/fesm2022/rt-tools-ui-kit-v2-button.mjs.map +1 -0
- package/fesm2022/rt-tools-ui-kit-v2-calendar.mjs +152 -0
- package/fesm2022/rt-tools-ui-kit-v2-calendar.mjs.map +1 -0
- package/fesm2022/rt-tools-ui-kit-v2-card.mjs +72 -0
- package/fesm2022/rt-tools-ui-kit-v2-card.mjs.map +1 -0
- package/fesm2022/rt-tools-ui-kit-v2-checkbox.mjs +111 -0
- package/fesm2022/rt-tools-ui-kit-v2-checkbox.mjs.map +1 -0
- package/fesm2022/rt-tools-ui-kit-v2-collapsible-text.mjs +76 -0
- package/fesm2022/rt-tools-ui-kit-v2-collapsible-text.mjs.map +1 -0
- package/fesm2022/rt-tools-ui-kit-v2-confirm-popover.mjs +255 -0
- package/fesm2022/rt-tools-ui-kit-v2-confirm-popover.mjs.map +1 -0
- package/fesm2022/rt-tools-ui-kit-v2-container.mjs +1326 -0
- package/fesm2022/rt-tools-ui-kit-v2-container.mjs.map +1 -0
- package/fesm2022/rt-tools-ui-kit-v2-core.mjs +2590 -0
- package/fesm2022/rt-tools-ui-kit-v2-core.mjs.map +1 -0
- package/fesm2022/rt-tools-ui-kit-v2-counter-row.mjs +45 -0
- package/fesm2022/rt-tools-ui-kit-v2-counter-row.mjs.map +1 -0
- package/fesm2022/rt-tools-ui-kit-v2-counter.mjs +158 -0
- package/fesm2022/rt-tools-ui-kit-v2-counter.mjs.map +1 -0
- package/fesm2022/rt-tools-ui-kit-v2-data-list.mjs +894 -0
- package/fesm2022/rt-tools-ui-kit-v2-data-list.mjs.map +1 -0
- package/fesm2022/rt-tools-ui-kit-v2-data-table.mjs +1217 -0
- package/fesm2022/rt-tools-ui-kit-v2-data-table.mjs.map +1 -0
- package/fesm2022/rt-tools-ui-kit-v2-date-picker.mjs +779 -0
- package/fesm2022/rt-tools-ui-kit-v2-date-picker.mjs.map +1 -0
- package/fesm2022/rt-tools-ui-kit-v2-date-range.mjs +573 -0
- package/fesm2022/rt-tools-ui-kit-v2-date-range.mjs.map +1 -0
- package/fesm2022/rt-tools-ui-kit-v2-delta-view.mjs +141 -0
- package/fesm2022/rt-tools-ui-kit-v2-delta-view.mjs.map +1 -0
- package/fesm2022/rt-tools-ui-kit-v2-detail-list.mjs +68 -0
- package/fesm2022/rt-tools-ui-kit-v2-detail-list.mjs.map +1 -0
- package/fesm2022/rt-tools-ui-kit-v2-dialog.mjs +478 -0
- package/fesm2022/rt-tools-ui-kit-v2-dialog.mjs.map +1 -0
- package/fesm2022/rt-tools-ui-kit-v2-dot-field.mjs +183 -0
- package/fesm2022/rt-tools-ui-kit-v2-dot-field.mjs.map +1 -0
- package/fesm2022/rt-tools-ui-kit-v2-download-link.mjs +44 -0
- package/fesm2022/rt-tools-ui-kit-v2-download-link.mjs.map +1 -0
- package/fesm2022/rt-tools-ui-kit-v2-dynamic-list.mjs +260 -0
- package/fesm2022/rt-tools-ui-kit-v2-dynamic-list.mjs.map +1 -0
- package/fesm2022/rt-tools-ui-kit-v2-dynamic-selector.mjs +937 -0
- package/fesm2022/rt-tools-ui-kit-v2-dynamic-selector.mjs.map +1 -0
- package/fesm2022/rt-tools-ui-kit-v2-empty-state.mjs +56 -0
- package/fesm2022/rt-tools-ui-kit-v2-empty-state.mjs.map +1 -0
- package/fesm2022/rt-tools-ui-kit-v2-expansion-panel.mjs +107 -0
- package/fesm2022/rt-tools-ui-kit-v2-expansion-panel.mjs.map +1 -0
- package/fesm2022/rt-tools-ui-kit-v2-field.mjs +183 -0
- package/fesm2022/rt-tools-ui-kit-v2-field.mjs.map +1 -0
- package/fesm2022/rt-tools-ui-kit-v2-file-card.mjs +219 -0
- package/fesm2022/rt-tools-ui-kit-v2-file-card.mjs.map +1 -0
- package/fesm2022/rt-tools-ui-kit-v2-file-drop.mjs +214 -0
- package/fesm2022/rt-tools-ui-kit-v2-file-drop.mjs.map +1 -0
- package/fesm2022/rt-tools-ui-kit-v2-file-input.mjs +117 -0
- package/fesm2022/rt-tools-ui-kit-v2-file-input.mjs.map +1 -0
- package/fesm2022/rt-tools-ui-kit-v2-file-list.mjs +32 -0
- package/fesm2022/rt-tools-ui-kit-v2-file-list.mjs.map +1 -0
- package/fesm2022/rt-tools-ui-kit-v2-filter-control.mjs +91 -0
- package/fesm2022/rt-tools-ui-kit-v2-filter-control.mjs.map +1 -0
- package/fesm2022/rt-tools-ui-kit-v2-form-control.mjs +220 -0
- package/fesm2022/rt-tools-ui-kit-v2-form-control.mjs.map +1 -0
- package/fesm2022/rt-tools-ui-kit-v2-header.mjs +72 -0
- package/fesm2022/rt-tools-ui-kit-v2-header.mjs.map +1 -0
- package/fesm2022/rt-tools-ui-kit-v2-icon-button.mjs +163 -0
- package/fesm2022/rt-tools-ui-kit-v2-icon-button.mjs.map +1 -0
- package/fesm2022/rt-tools-ui-kit-v2-icon.mjs +674 -0
- package/fesm2022/rt-tools-ui-kit-v2-icon.mjs.map +1 -0
- package/fesm2022/rt-tools-ui-kit-v2-image-cropper.mjs +540 -0
- package/fesm2022/rt-tools-ui-kit-v2-image-cropper.mjs.map +1 -0
- package/fesm2022/rt-tools-ui-kit-v2-image-upload.mjs +227 -0
- package/fesm2022/rt-tools-ui-kit-v2-image-upload.mjs.map +1 -0
- package/fesm2022/rt-tools-ui-kit-v2-info-item.mjs +37 -0
- package/fesm2022/rt-tools-ui-kit-v2-info-item.mjs.map +1 -0
- package/fesm2022/rt-tools-ui-kit-v2-input-number.mjs +361 -0
- package/fesm2022/rt-tools-ui-kit-v2-input-number.mjs.map +1 -0
- package/fesm2022/rt-tools-ui-kit-v2-input.mjs +143 -0
- package/fesm2022/rt-tools-ui-kit-v2-input.mjs.map +1 -0
- package/fesm2022/rt-tools-ui-kit-v2-live-badge.mjs +49 -0
- package/fesm2022/rt-tools-ui-kit-v2-live-badge.mjs.map +1 -0
- package/fesm2022/rt-tools-ui-kit-v2-logo.mjs +97 -0
- package/fesm2022/rt-tools-ui-kit-v2-logo.mjs.map +1 -0
- package/fesm2022/rt-tools-ui-kit-v2-markdown-text.mjs +57 -0
- package/fesm2022/rt-tools-ui-kit-v2-markdown-text.mjs.map +1 -0
- package/fesm2022/rt-tools-ui-kit-v2-menu.mjs +537 -0
- package/fesm2022/rt-tools-ui-kit-v2-menu.mjs.map +1 -0
- package/fesm2022/rt-tools-ui-kit-v2-message.mjs +105 -0
- package/fesm2022/rt-tools-ui-kit-v2-message.mjs.map +1 -0
- package/fesm2022/rt-tools-ui-kit-v2-money-list.mjs +71 -0
- package/fesm2022/rt-tools-ui-kit-v2-money-list.mjs.map +1 -0
- package/fesm2022/rt-tools-ui-kit-v2-multiselect.mjs +315 -0
- package/fesm2022/rt-tools-ui-kit-v2-multiselect.mjs.map +1 -0
- package/fesm2022/rt-tools-ui-kit-v2-night-grid.mjs +51 -0
- package/fesm2022/rt-tools-ui-kit-v2-night-grid.mjs.map +1 -0
- package/fesm2022/rt-tools-ui-kit-v2-note.mjs +44 -0
- package/fesm2022/rt-tools-ui-kit-v2-note.mjs.map +1 -0
- package/fesm2022/rt-tools-ui-kit-v2-notifications-bell.mjs +54 -0
- package/fesm2022/rt-tools-ui-kit-v2-notifications-bell.mjs.map +1 -0
- package/fesm2022/rt-tools-ui-kit-v2-page-header.mjs +339 -0
- package/fesm2022/rt-tools-ui-kit-v2-page-header.mjs.map +1 -0
- package/fesm2022/rt-tools-ui-kit-v2-pagination.mjs +187 -0
- package/fesm2022/rt-tools-ui-kit-v2-pagination.mjs.map +1 -0
- package/fesm2022/rt-tools-ui-kit-v2-photo-viewer.mjs +170 -0
- package/fesm2022/rt-tools-ui-kit-v2-photo-viewer.mjs.map +1 -0
- package/fesm2022/rt-tools-ui-kit-v2-popover.mjs +312 -0
- package/fesm2022/rt-tools-ui-kit-v2-popover.mjs.map +1 -0
- package/fesm2022/rt-tools-ui-kit-v2-radio-button.mjs +174 -0
- package/fesm2022/rt-tools-ui-kit-v2-radio-button.mjs.map +1 -0
- package/fesm2022/rt-tools-ui-kit-v2-radius.mjs +56 -0
- package/fesm2022/rt-tools-ui-kit-v2-radius.mjs.map +1 -0
- package/fesm2022/rt-tools-ui-kit-v2-ripple.mjs +118 -0
- package/fesm2022/rt-tools-ui-kit-v2-ripple.mjs.map +1 -0
- package/fesm2022/rt-tools-ui-kit-v2-scroll-area.mjs +290 -0
- package/fesm2022/rt-tools-ui-kit-v2-scroll-area.mjs.map +1 -0
- package/fesm2022/rt-tools-ui-kit-v2-section-nav.mjs +37 -0
- package/fesm2022/rt-tools-ui-kit-v2-section-nav.mjs.map +1 -0
- package/fesm2022/rt-tools-ui-kit-v2-select.mjs +495 -0
- package/fesm2022/rt-tools-ui-kit-v2-select.mjs.map +1 -0
- package/fesm2022/rt-tools-ui-kit-v2-side-menu.mjs +1493 -0
- package/fesm2022/rt-tools-ui-kit-v2-side-menu.mjs.map +1 -0
- package/fesm2022/rt-tools-ui-kit-v2-skeleton-wrapper.mjs +49 -0
- package/fesm2022/rt-tools-ui-kit-v2-skeleton-wrapper.mjs.map +1 -0
- package/fesm2022/rt-tools-ui-kit-v2-skeleton.mjs +123 -0
- package/fesm2022/rt-tools-ui-kit-v2-skeleton.mjs.map +1 -0
- package/fesm2022/rt-tools-ui-kit-v2-spinner.mjs +70 -0
- package/fesm2022/rt-tools-ui-kit-v2-spinner.mjs.map +1 -0
- package/fesm2022/rt-tools-ui-kit-v2-split-button.mjs +92 -0
- package/fesm2022/rt-tools-ui-kit-v2-split-button.mjs.map +1 -0
- package/fesm2022/rt-tools-ui-kit-v2-stat-tile.mjs +147 -0
- package/fesm2022/rt-tools-ui-kit-v2-stat-tile.mjs.map +1 -0
- package/fesm2022/rt-tools-ui-kit-v2-stepper.mjs +117 -0
- package/fesm2022/rt-tools-ui-kit-v2-stepper.mjs.map +1 -0
- package/fesm2022/rt-tools-ui-kit-v2-table.mjs +1636 -0
- package/fesm2022/rt-tools-ui-kit-v2-table.mjs.map +1 -0
- package/fesm2022/rt-tools-ui-kit-v2-tabs.mjs +350 -0
- package/fesm2022/rt-tools-ui-kit-v2-tabs.mjs.map +1 -0
- package/fesm2022/rt-tools-ui-kit-v2-tag.mjs +122 -0
- package/fesm2022/rt-tools-ui-kit-v2-tag.mjs.map +1 -0
- package/fesm2022/rt-tools-ui-kit-v2-textarea.mjs +85 -0
- package/fesm2022/rt-tools-ui-kit-v2-textarea.mjs.map +1 -0
- package/fesm2022/rt-tools-ui-kit-v2-theme-toggle.mjs +73 -0
- package/fesm2022/rt-tools-ui-kit-v2-theme-toggle.mjs.map +1 -0
- package/fesm2022/rt-tools-ui-kit-v2-thread-list.mjs +196 -0
- package/fesm2022/rt-tools-ui-kit-v2-thread-list.mjs.map +1 -0
- package/fesm2022/rt-tools-ui-kit-v2-timeline.mjs +39 -0
- package/fesm2022/rt-tools-ui-kit-v2-timeline.mjs.map +1 -0
- package/fesm2022/rt-tools-ui-kit-v2-toast.mjs +338 -0
- package/fesm2022/rt-tools-ui-kit-v2-toast.mjs.map +1 -0
- package/fesm2022/rt-tools-ui-kit-v2-toggle-button-group.mjs +132 -0
- package/fesm2022/rt-tools-ui-kit-v2-toggle-button-group.mjs.map +1 -0
- package/fesm2022/rt-tools-ui-kit-v2-toggle-switch.mjs +162 -0
- package/fesm2022/rt-tools-ui-kit-v2-toggle-switch.mjs.map +1 -0
- package/fesm2022/rt-tools-ui-kit-v2-toolbar.mjs +135 -0
- package/fesm2022/rt-tools-ui-kit-v2-toolbar.mjs.map +1 -0
- package/fesm2022/rt-tools-ui-kit-v2-tooltip.mjs +214 -0
- package/fesm2022/rt-tools-ui-kit-v2-tooltip.mjs.map +1 -0
- package/fesm2022/rt-tools-ui-kit-v2-welcome-dialog.mjs +64 -0
- package/fesm2022/rt-tools-ui-kit-v2-welcome-dialog.mjs.map +1 -0
- package/fesm2022/rt-tools-ui-kit-v2-workspace-details.mjs +263 -0
- package/fesm2022/rt-tools-ui-kit-v2-workspace-details.mjs.map +1 -0
- package/fesm2022/rt-tools-ui-kit-v2-workspace.mjs +296 -0
- package/fesm2022/rt-tools-ui-kit-v2-workspace.mjs.map +1 -0
- package/fesm2022/rt-tools-ui-kit-v2.mjs +91 -23819
- package/fesm2022/rt-tools-ui-kit-v2.mjs.map +1 -1
- package/package.json +349 -1
- package/rt-tools-ui-kit-v2-0.18.0.tgz +0 -0
- package/src/lib/components/dot-field/CONTEXT.md +31 -0
- package/src/lib/components/dot-field/rt-dot-field.component.scss +20 -0
- package/src/lib/components/dot-field/stories/component/CONTEXT.md +14 -0
- package/src/lib/components/dot-field/stories/component/test-dot-field.component.scss +31 -0
- package/src/lib/components/field/CONTEXT.md +18 -2
- package/src/lib/components/select/rt-select.component.scss +4 -0
- package/src/styles/_semantic.scss +1 -1
- package/styles/tokens.css +8 -8
- package/types/rt-tools-ui-kit-v2-accordion.d.ts +30 -0
- package/types/rt-tools-ui-kit-v2-action-bar.d.ts +140 -0
- package/types/rt-tools-ui-kit-v2-aside-section.d.ts +25 -0
- package/types/rt-tools-ui-kit-v2-aside.d.ts +436 -0
- package/types/rt-tools-ui-kit-v2-autocomplete.d.ts +78 -0
- package/types/rt-tools-ui-kit-v2-bar-list.d.ts +41 -0
- package/types/rt-tools-ui-kit-v2-bottom-sheet.d.ts +20 -0
- package/types/rt-tools-ui-kit-v2-button.d.ts +76 -0
- package/types/rt-tools-ui-kit-v2-calendar.d.ts +96 -0
- package/types/rt-tools-ui-kit-v2-card.d.ts +38 -0
- package/types/rt-tools-ui-kit-v2-checkbox.d.ts +46 -0
- package/types/rt-tools-ui-kit-v2-collapsible-text.d.ts +20 -0
- package/types/rt-tools-ui-kit-v2-confirm-popover.d.ts +85 -0
- package/types/rt-tools-ui-kit-v2-container.d.ts +425 -0
- package/types/rt-tools-ui-kit-v2-core.d.ts +1222 -0
- package/types/rt-tools-ui-kit-v2-counter-row.d.ts +22 -0
- package/types/rt-tools-ui-kit-v2-counter.d.ts +70 -0
- package/types/rt-tools-ui-kit-v2-data-list.d.ts +334 -0
- package/types/rt-tools-ui-kit-v2-data-table.d.ts +494 -0
- package/types/rt-tools-ui-kit-v2-date-picker.d.ts +181 -0
- package/types/rt-tools-ui-kit-v2-date-range.d.ts +98 -0
- package/types/rt-tools-ui-kit-v2-delta-view.d.ts +20 -0
- package/types/rt-tools-ui-kit-v2-detail-list.d.ts +33 -0
- package/types/rt-tools-ui-kit-v2-dialog.d.ts +287 -0
- package/types/rt-tools-ui-kit-v2-dot-field.d.ts +17 -0
- package/types/rt-tools-ui-kit-v2-download-link.d.ts +17 -0
- package/types/rt-tools-ui-kit-v2-dynamic-list.d.ts +139 -0
- package/types/rt-tools-ui-kit-v2-dynamic-selector.d.ts +384 -0
- package/types/rt-tools-ui-kit-v2-empty-state.d.ts +29 -0
- package/types/rt-tools-ui-kit-v2-expansion-panel.d.ts +57 -0
- package/types/rt-tools-ui-kit-v2-field.d.ts +82 -0
- package/types/rt-tools-ui-kit-v2-file-card.d.ts +114 -0
- package/types/rt-tools-ui-kit-v2-file-drop.d.ts +75 -0
- package/types/rt-tools-ui-kit-v2-file-input.d.ts +48 -0
- package/types/rt-tools-ui-kit-v2-file-list.d.ts +13 -0
- package/types/rt-tools-ui-kit-v2-filter-control.d.ts +72 -0
- package/types/rt-tools-ui-kit-v2-form-control.d.ts +74 -0
- package/types/rt-tools-ui-kit-v2-header.d.ts +40 -0
- package/types/rt-tools-ui-kit-v2-icon-button.d.ts +113 -0
- package/types/rt-tools-ui-kit-v2-icon.d.ts +238 -0
- package/types/rt-tools-ui-kit-v2-image-cropper.d.ts +168 -0
- package/types/rt-tools-ui-kit-v2-image-upload.d.ts +102 -0
- package/types/rt-tools-ui-kit-v2-info-item.d.ts +13 -0
- package/types/rt-tools-ui-kit-v2-input-number.d.ts +67 -0
- package/types/rt-tools-ui-kit-v2-input.d.ts +54 -0
- package/types/rt-tools-ui-kit-v2-live-badge.d.ts +23 -0
- package/types/rt-tools-ui-kit-v2-logo.d.ts +58 -0
- package/types/rt-tools-ui-kit-v2-markdown-text.d.ts +30 -0
- package/types/rt-tools-ui-kit-v2-menu.d.ts +217 -0
- package/types/rt-tools-ui-kit-v2-message.d.ts +56 -0
- package/types/rt-tools-ui-kit-v2-money-list.d.ts +34 -0
- package/types/rt-tools-ui-kit-v2-multiselect.d.ts +93 -0
- package/types/rt-tools-ui-kit-v2-night-grid.d.ts +39 -0
- package/types/rt-tools-ui-kit-v2-note.d.ts +21 -0
- package/types/rt-tools-ui-kit-v2-notifications-bell.d.ts +23 -0
- package/types/rt-tools-ui-kit-v2-page-header.d.ts +173 -0
- package/types/rt-tools-ui-kit-v2-pagination.d.ts +64 -0
- package/types/rt-tools-ui-kit-v2-photo-viewer.d.ts +98 -0
- package/types/rt-tools-ui-kit-v2-popover.d.ts +79 -0
- package/types/rt-tools-ui-kit-v2-radio-button.d.ts +61 -0
- package/types/rt-tools-ui-kit-v2-radius.d.ts +37 -0
- package/types/rt-tools-ui-kit-v2-ripple.d.ts +39 -0
- package/types/rt-tools-ui-kit-v2-scroll-area.d.ts +91 -0
- package/types/rt-tools-ui-kit-v2-section-nav.d.ts +23 -0
- package/types/rt-tools-ui-kit-v2-select.d.ts +215 -0
- package/types/rt-tools-ui-kit-v2-side-menu.d.ts +483 -0
- package/types/rt-tools-ui-kit-v2-skeleton-wrapper.d.ts +32 -0
- package/types/rt-tools-ui-kit-v2-skeleton.d.ts +41 -0
- package/types/rt-tools-ui-kit-v2-spinner.d.ts +56 -0
- package/types/rt-tools-ui-kit-v2-split-button.d.ts +72 -0
- package/types/rt-tools-ui-kit-v2-stat-tile.d.ts +81 -0
- package/types/rt-tools-ui-kit-v2-stepper.d.ts +51 -0
- package/types/rt-tools-ui-kit-v2-table.d.ts +739 -0
- package/types/rt-tools-ui-kit-v2-tabs.d.ts +153 -0
- package/types/rt-tools-ui-kit-v2-tag.d.ts +70 -0
- package/types/rt-tools-ui-kit-v2-textarea.d.ts +36 -0
- package/types/rt-tools-ui-kit-v2-theme-toggle.d.ts +43 -0
- package/types/rt-tools-ui-kit-v2-thread-list.d.ts +111 -0
- package/types/rt-tools-ui-kit-v2-timeline.d.ts +35 -0
- package/types/rt-tools-ui-kit-v2-toast.d.ts +103 -0
- package/types/rt-tools-ui-kit-v2-toggle-button-group.d.ts +109 -0
- package/types/rt-tools-ui-kit-v2-toggle-switch.d.ts +85 -0
- package/types/rt-tools-ui-kit-v2-toolbar.d.ts +66 -0
- package/types/rt-tools-ui-kit-v2-tooltip.d.ts +74 -0
- package/types/rt-tools-ui-kit-v2-welcome-dialog.d.ts +33 -0
- package/types/rt-tools-ui-kit-v2-workspace-details.d.ts +128 -0
- package/types/rt-tools-ui-kit-v2-workspace.d.ts +84 -0
- package/types/rt-tools-ui-kit-v2.d.ts +87 -9599
- package/rt-tools-ui-kit-v2-0.17.0.tgz +0 -0
|
@@ -0,0 +1,540 @@
|
|
|
1
|
+
import { DOCUMENT } from '@angular/common';
|
|
2
|
+
import * as i0 from '@angular/core';
|
|
3
|
+
import { numberAttribute, inject, DestroyRef, signal, computed, viewChild, input, booleanAttribute, output, effect, untracked, afterNextRender, ViewEncapsulation, ChangeDetectionStrategy, Component } from '@angular/core';
|
|
4
|
+
import { WINDOW, PlatformService, BlockDirective, ElemDirective, ModDirective } from '@rt-tools/core';
|
|
5
|
+
import { RT_KIT_LABELS } from '@rt-tools/ui-kit-v2/core';
|
|
6
|
+
import { RtSpinnerComponent } from '@rt-tools/ui-kit-v2/spinner';
|
|
7
|
+
|
|
8
|
+
/**
|
|
9
|
+
* Чистая логика обрезки: вписывание исходника в поле, рамка в пикселях
|
|
10
|
+
* исходника, её движение и растяжение, перевод клавиш и выбор формата.
|
|
11
|
+
* Компонент только переводит указатель в сдвиги и рисует то, что вернулось.
|
|
12
|
+
*/
|
|
13
|
+
/** Все восемь ручек по часовой стрелке от левого верхнего угла */
|
|
14
|
+
const RT_IMAGE_CROPPER_HANDLES = ['nw', 'n', 'ne', 'e', 'se', 's', 'sw', 'w'];
|
|
15
|
+
/** Шаг клавиш в пикселях поля: стрелка и стрелка с Shift */
|
|
16
|
+
const RT_IMAGE_CROPPER_KEY_STEP = 1;
|
|
17
|
+
const RT_IMAGE_CROPPER_KEY_STEP_LARGE = 10;
|
|
18
|
+
/** Качество по умолчанию — то же, что у загрузчика первого кита */
|
|
19
|
+
const RT_IMAGE_CROPPER_QUALITY = 92;
|
|
20
|
+
const OWN_TYPES = ['image/png', 'image/jpeg', 'image/webp'];
|
|
21
|
+
function clamp(value, min, max) {
|
|
22
|
+
return Math.max(min, Math.min(max, value));
|
|
23
|
+
}
|
|
24
|
+
/**
|
|
25
|
+
* Вписывает исходник в поле целиком, с его пропорциями, по центру. Ни одна часть
|
|
26
|
+
* картинки не срезается полем, и ни одна не растянута.
|
|
27
|
+
*/
|
|
28
|
+
function fitSource(source, field) {
|
|
29
|
+
if (source.width <= 0 || source.height <= 0 || field.width <= 0 || field.height <= 0) {
|
|
30
|
+
return { scale: 0, offsetX: 0, offsetY: 0, width: 0, height: 0 };
|
|
31
|
+
}
|
|
32
|
+
const scale = Math.min(field.width / source.width, field.height / source.height);
|
|
33
|
+
const width = source.width * scale;
|
|
34
|
+
const height = source.height * scale;
|
|
35
|
+
return { offsetX: (field.width - width) / 2, offsetY: (field.height - height) / 2, scale, width, height };
|
|
36
|
+
}
|
|
37
|
+
/**
|
|
38
|
+
* Пропорция, которую держит рамка. Круглый вид держит один к одному при любой
|
|
39
|
+
* заданной; заданная не числом или не больше нуля значит свободную рамку.
|
|
40
|
+
*/
|
|
41
|
+
function frameRatio(ratio, round) {
|
|
42
|
+
if (round) {
|
|
43
|
+
return 1;
|
|
44
|
+
}
|
|
45
|
+
return typeof ratio === 'number' && Number.isFinite(ratio) && ratio > 0 ? ratio : null;
|
|
46
|
+
}
|
|
47
|
+
/**
|
|
48
|
+
* Начальная рамка — наибольшая, какую позволяет пропорция, по центру исходника.
|
|
49
|
+
* Свободная начинается как весь исходник.
|
|
50
|
+
*/
|
|
51
|
+
function initialFrame(source, ratio) {
|
|
52
|
+
if (ratio === null) {
|
|
53
|
+
return { x: 0, y: 0, width: source.width, height: source.height };
|
|
54
|
+
}
|
|
55
|
+
const width = Math.min(source.width, source.height * ratio);
|
|
56
|
+
const height = width / ratio;
|
|
57
|
+
return { x: (source.width - width) / 2, y: (source.height - height) / 2, width, height };
|
|
58
|
+
}
|
|
59
|
+
/** Сдвиг рамки целиком: размер тот же, у края исходника рамка останавливается */
|
|
60
|
+
function moveFrame(frame, delta, source) {
|
|
61
|
+
return {
|
|
62
|
+
x: clamp(frame.x + delta.dx, 0, Math.max(0, source.width - frame.width)),
|
|
63
|
+
y: clamp(frame.y + delta.dy, 0, Math.max(0, source.height - frame.height)),
|
|
64
|
+
width: frame.width,
|
|
65
|
+
height: frame.height,
|
|
66
|
+
};
|
|
67
|
+
}
|
|
68
|
+
/** Знак оси по ручке: к концу оси, к началу, или ось не тянется */
|
|
69
|
+
function axisSign(handle, forward, backward) {
|
|
70
|
+
if (handle.includes(forward)) {
|
|
71
|
+
return 1;
|
|
72
|
+
}
|
|
73
|
+
return handle.includes(backward) ? -1 : 0;
|
|
74
|
+
}
|
|
75
|
+
/** По каким осям и в какую сторону тянет ручка */
|
|
76
|
+
function handleDirection(handle) {
|
|
77
|
+
return { x: axisSign(handle, 'e', 'w'), y: axisSign(handle, 's', 'n') };
|
|
78
|
+
}
|
|
79
|
+
/**
|
|
80
|
+
* Наибольший размер по оси: от неподвижной стороны до края исходника, а для оси,
|
|
81
|
+
* которую ручка не тянет, — удвоенное расстояние от центра до ближнего края.
|
|
82
|
+
*/
|
|
83
|
+
function axisRoom(start, size, limit, direction) {
|
|
84
|
+
if (direction > 0) {
|
|
85
|
+
return limit - start;
|
|
86
|
+
}
|
|
87
|
+
if (direction < 0) {
|
|
88
|
+
return start + size;
|
|
89
|
+
}
|
|
90
|
+
const centre = start + size / 2;
|
|
91
|
+
return 2 * Math.min(centre, limit - centre);
|
|
92
|
+
}
|
|
93
|
+
/** Где рамка встаёт на оси: от неподвижной стороны, или вокруг центра для оси, которую ручка не тянет */
|
|
94
|
+
function axisStart(start, size, next, direction) {
|
|
95
|
+
if (direction > 0) {
|
|
96
|
+
return start;
|
|
97
|
+
}
|
|
98
|
+
if (direction < 0) {
|
|
99
|
+
return start + size - next;
|
|
100
|
+
}
|
|
101
|
+
return start + size / 2 - next / 2;
|
|
102
|
+
}
|
|
103
|
+
/** Свободная рамка: каждая ось тянется сама, ось без ручки остаётся как была */
|
|
104
|
+
function resizeFree(frame, direction, delta, source, least) {
|
|
105
|
+
let { x, y, width, height } = frame;
|
|
106
|
+
if (direction.x !== 0) {
|
|
107
|
+
const room = axisRoom(frame.x, frame.width, source.width, direction.x);
|
|
108
|
+
width = clamp(frame.width + direction.x * delta.dx, Math.min(least, room), room);
|
|
109
|
+
x = axisStart(frame.x, frame.width, width, direction.x);
|
|
110
|
+
}
|
|
111
|
+
if (direction.y !== 0) {
|
|
112
|
+
const room = axisRoom(frame.y, frame.height, source.height, direction.y);
|
|
113
|
+
height = clamp(frame.height + direction.y * delta.dy, Math.min(least, room), room);
|
|
114
|
+
y = axisStart(frame.y, frame.height, height, direction.y);
|
|
115
|
+
}
|
|
116
|
+
return { x, y, width, height };
|
|
117
|
+
}
|
|
118
|
+
/**
|
|
119
|
+
* Ширина, которую просит сдвиг при заданной пропорции. Угол берёт ту ось, по
|
|
120
|
+
* которой сдвиг больше; сторона — свою ось.
|
|
121
|
+
*/
|
|
122
|
+
function wantedRatioWidth(frame, direction, delta, ratio) {
|
|
123
|
+
const byWidth = frame.width + direction.x * delta.dx;
|
|
124
|
+
const byHeight = (frame.height + direction.y * delta.dy) * ratio;
|
|
125
|
+
if (direction.x === 0) {
|
|
126
|
+
return byHeight;
|
|
127
|
+
}
|
|
128
|
+
if (direction.y === 0) {
|
|
129
|
+
return byWidth;
|
|
130
|
+
}
|
|
131
|
+
return Math.abs(delta.dx) >= Math.abs(delta.dy * ratio) ? byWidth : byHeight;
|
|
132
|
+
}
|
|
133
|
+
/**
|
|
134
|
+
* Растяжение рамки за ручку. Сторона или угол напротив ручки стоит на месте;
|
|
135
|
+
* рамка не выходит за исходник и не становится меньше наименьшего размера; рамка
|
|
136
|
+
* с пропорцией держит её, а боковая ручка тянет её вокруг центра второй оси.
|
|
137
|
+
*/
|
|
138
|
+
function resizeFrame(frame, handle, delta, source, ratio, minSize) {
|
|
139
|
+
const direction = handleDirection(handle);
|
|
140
|
+
const least = Math.max(0, minSize);
|
|
141
|
+
if (ratio === null) {
|
|
142
|
+
return resizeFree(frame, direction, delta, source, least);
|
|
143
|
+
}
|
|
144
|
+
const roomWidth = Math.min(axisRoom(frame.x, frame.width, source.width, direction.x), axisRoom(frame.y, frame.height, source.height, direction.y) * ratio);
|
|
145
|
+
const leastWidth = Math.min(Math.max(least, least * ratio), roomWidth);
|
|
146
|
+
const width = clamp(wantedRatioWidth(frame, direction, delta, ratio), leastWidth, roomWidth);
|
|
147
|
+
const height = width / ratio;
|
|
148
|
+
return {
|
|
149
|
+
x: axisStart(frame.x, frame.width, width, direction.x),
|
|
150
|
+
y: axisStart(frame.y, frame.height, height, direction.y),
|
|
151
|
+
width,
|
|
152
|
+
height,
|
|
153
|
+
};
|
|
154
|
+
}
|
|
155
|
+
/**
|
|
156
|
+
* Сдвиг от стрелки клавиатуры в пикселях исходника. Одно нажатие — пиксель поля,
|
|
157
|
+
* с Shift десять; не стрелка даёт `null`.
|
|
158
|
+
*/
|
|
159
|
+
function keyDelta(key, isLarge, scale) {
|
|
160
|
+
if (scale <= 0) {
|
|
161
|
+
return null;
|
|
162
|
+
}
|
|
163
|
+
const step = (isLarge ? RT_IMAGE_CROPPER_KEY_STEP_LARGE : RT_IMAGE_CROPPER_KEY_STEP) / scale;
|
|
164
|
+
switch (key) {
|
|
165
|
+
case 'ArrowLeft':
|
|
166
|
+
return { dx: -step, dy: 0 };
|
|
167
|
+
case 'ArrowRight':
|
|
168
|
+
return { dx: step, dy: 0 };
|
|
169
|
+
case 'ArrowUp':
|
|
170
|
+
return { dx: 0, dy: -step };
|
|
171
|
+
case 'ArrowDown':
|
|
172
|
+
return { dx: 0, dy: step };
|
|
173
|
+
default:
|
|
174
|
+
return null;
|
|
175
|
+
}
|
|
176
|
+
}
|
|
177
|
+
/** Сдвиг указателя в пикселях поля переводится в пиксели исходника */
|
|
178
|
+
function fieldDelta(dx, dy, scale) {
|
|
179
|
+
return scale > 0 ? { dx: dx / scale, dy: dy / scale } : { dx: 0, dy: 0 };
|
|
180
|
+
}
|
|
181
|
+
/** Рамка в пикселях поля — для рисования поверх вписанной картинки */
|
|
182
|
+
function frameInField(frame, fit) {
|
|
183
|
+
return {
|
|
184
|
+
x: fit.offsetX + frame.x * fit.scale,
|
|
185
|
+
y: fit.offsetY + frame.y * fit.scale,
|
|
186
|
+
width: frame.width * fit.scale,
|
|
187
|
+
height: frame.height * fit.scale,
|
|
188
|
+
};
|
|
189
|
+
}
|
|
190
|
+
/** Рамка в целых пикселях исходника — то, что вырезает холст; не меньше пикселя */
|
|
191
|
+
function cropArea(frame, source) {
|
|
192
|
+
const x = clamp(Math.round(frame.x), 0, Math.max(0, source.width - 1));
|
|
193
|
+
const y = clamp(Math.round(frame.y), 0, Math.max(0, source.height - 1));
|
|
194
|
+
return {
|
|
195
|
+
x,
|
|
196
|
+
y,
|
|
197
|
+
width: clamp(Math.round(frame.width), 1, Math.max(1, source.width - x)),
|
|
198
|
+
height: clamp(Math.round(frame.height), 1, Math.max(1, source.height - y)),
|
|
199
|
+
};
|
|
200
|
+
}
|
|
201
|
+
/**
|
|
202
|
+
* Тип результата. Без выбранного формата берётся формат исходника, и png, когда
|
|
203
|
+
* он не из трёх.
|
|
204
|
+
*/
|
|
205
|
+
function resultType(format, sourceType) {
|
|
206
|
+
if (format) {
|
|
207
|
+
return `image/${format}`;
|
|
208
|
+
}
|
|
209
|
+
return OWN_TYPES.includes(sourceType) ? sourceType : 'image/png';
|
|
210
|
+
}
|
|
211
|
+
/** Качество холста — доля единицы; вход берёт проценты */
|
|
212
|
+
function resultQuality(quality) {
|
|
213
|
+
return Number.isFinite(quality) ? clamp(quality, 0, 100) / 100 : RT_IMAGE_CROPPER_QUALITY / 100;
|
|
214
|
+
}
|
|
215
|
+
/** Имя файла результата: основа имени исходника и расширение по типу результата */
|
|
216
|
+
function resultFileName(sourceName, type) {
|
|
217
|
+
const extension = type === 'image/jpeg' ? 'jpg' : type.replace('image/', '');
|
|
218
|
+
const dot = sourceName.lastIndexOf('.');
|
|
219
|
+
let base = sourceName || 'image';
|
|
220
|
+
if (dot > 0) {
|
|
221
|
+
base = sourceName.slice(0, dot);
|
|
222
|
+
}
|
|
223
|
+
return `${base}.${extension}`;
|
|
224
|
+
}
|
|
225
|
+
|
|
226
|
+
const BEM_BLOCK = 'rt-image-cropper';
|
|
227
|
+
/** Наименьший размер рамки по умолчанию, в пикселях исходника */
|
|
228
|
+
const DEFAULT_MIN_SIZE = 16;
|
|
229
|
+
/** Подпись каждой ручки — ключ словаря кита */
|
|
230
|
+
const HANDLE_LABELS = {
|
|
231
|
+
n: 'uiImageCropperHandleN',
|
|
232
|
+
s: 'uiImageCropperHandleS',
|
|
233
|
+
e: 'uiImageCropperHandleE',
|
|
234
|
+
w: 'uiImageCropperHandleW',
|
|
235
|
+
ne: 'uiImageCropperHandleNe',
|
|
236
|
+
nw: 'uiImageCropperHandleNw',
|
|
237
|
+
se: 'uiImageCropperHandleSe',
|
|
238
|
+
sw: 'uiImageCropperHandleSw',
|
|
239
|
+
};
|
|
240
|
+
function sameRect(a, b) {
|
|
241
|
+
return a.x === b.x && a.y === b.y && a.width === b.width && a.height === b.height;
|
|
242
|
+
}
|
|
243
|
+
function optionalNumber(value) {
|
|
244
|
+
return value === null || value === undefined || value === '' ? null : numberAttribute(value, 0);
|
|
245
|
+
}
|
|
246
|
+
/**
|
|
247
|
+
* Обрезка изображения: исходник вписан в поле целиком, поверх — рамка с восемью
|
|
248
|
+
* ручками. Рамка живёт в пикселях исходника и двигается указателем, пальцем и
|
|
249
|
+
* стрелками; после прочтения исходника и после каждого законченного изменения
|
|
250
|
+
* компонент отдаёт файл, вырезанный рамкой, в выбранном формате и качестве.
|
|
251
|
+
*
|
|
252
|
+
* Поворот снимка по EXIF делает сам браузер: картинка и холст читают исходник с
|
|
253
|
+
* `image-orientation: from-image`, и размеры, которые видит логика, уже
|
|
254
|
+
* повёрнутые.
|
|
255
|
+
*/
|
|
256
|
+
class RtImageCropperComponent {
|
|
257
|
+
#destroyRef;
|
|
258
|
+
#window;
|
|
259
|
+
#document;
|
|
260
|
+
#platform;
|
|
261
|
+
#fieldSize;
|
|
262
|
+
#source;
|
|
263
|
+
#frame;
|
|
264
|
+
#ratio;
|
|
265
|
+
#fit;
|
|
266
|
+
#image;
|
|
267
|
+
/** Картинка, которая сейчас читается: ответ прежней после смены исходника не принимается */
|
|
268
|
+
#pending;
|
|
269
|
+
#sourceType;
|
|
270
|
+
#sourceName;
|
|
271
|
+
#drag;
|
|
272
|
+
/** Номер последнего запроса результата: поздний ответ холста по старой рамке отбрасывается */
|
|
273
|
+
#resultTicket;
|
|
274
|
+
constructor() {
|
|
275
|
+
this.#destroyRef = inject(DestroyRef);
|
|
276
|
+
this.#window = inject(WINDOW);
|
|
277
|
+
this.#document = inject(DOCUMENT);
|
|
278
|
+
this.#platform = inject(PlatformService);
|
|
279
|
+
this.#fieldSize = signal({ width: 0, height: 0 }, /* @ts-ignore */
|
|
280
|
+
...(ngDevMode ? [{ debugName: "#fieldSize" }] : /* istanbul ignore next */ []));
|
|
281
|
+
this.#source = signal({ width: 0, height: 0 }, /* @ts-ignore */
|
|
282
|
+
...(ngDevMode ? [{ debugName: "#source" }] : /* istanbul ignore next */ []));
|
|
283
|
+
this.#frame = signal({ x: 0, y: 0, width: 0, height: 0 }, /* @ts-ignore */
|
|
284
|
+
...(ngDevMode ? [{ debugName: "#frame" }] : /* istanbul ignore next */ []));
|
|
285
|
+
this.#ratio = computed(() => frameRatio(this.ratio(), this.round()), /* @ts-ignore */
|
|
286
|
+
...(ngDevMode ? [{ debugName: "#ratio" }] : /* istanbul ignore next */ []));
|
|
287
|
+
this.#fit = computed(() => fitSource(this.#source(), this.#fieldSize()), /* @ts-ignore */
|
|
288
|
+
...(ngDevMode ? [{ debugName: "#fit" }] : /* istanbul ignore next */ []));
|
|
289
|
+
this.#image = null;
|
|
290
|
+
/** Картинка, которая сейчас читается: ответ прежней после смены исходника не принимается */
|
|
291
|
+
this.#pending = null;
|
|
292
|
+
this.#sourceType = '';
|
|
293
|
+
this.#sourceName = '';
|
|
294
|
+
this.#drag = null;
|
|
295
|
+
/** Номер последнего запроса результата: поздний ответ холста по старой рамке отбрасывается */
|
|
296
|
+
this.#resultTicket = 0;
|
|
297
|
+
this.field = viewChild.required('field', /* @ts-ignore */
|
|
298
|
+
...(ngDevMode ? [{ debugName: "field" }] : /* istanbul ignore next */ []));
|
|
299
|
+
this.t = inject(RT_KIT_LABELS);
|
|
300
|
+
this.handles = RT_IMAGE_CROPPER_HANDLES;
|
|
301
|
+
this.handleLabels = HANDLE_LABELS;
|
|
302
|
+
this.state = signal('empty', /* @ts-ignore */
|
|
303
|
+
...(ngDevMode ? [{ debugName: "state" }] : /* istanbul ignore next */ []));
|
|
304
|
+
/** Текст пустого поля: свой, если задан, иначе подпись кита */
|
|
305
|
+
this.placeholderText = computed(() => this.placeholder() || this.t().uiImageCropperPlaceholder, /* @ts-ignore */
|
|
306
|
+
...(ngDevMode ? [{ debugName: "placeholderText" }] : /* istanbul ignore next */ []));
|
|
307
|
+
/** Адрес исходника для картинки в поле */
|
|
308
|
+
this.url = signal(null, /* @ts-ignore */
|
|
309
|
+
...(ngDevMode ? [{ debugName: "url" }] : /* istanbul ignore next */ []));
|
|
310
|
+
/** Где картинка лежит в поле, в пикселях поля */
|
|
311
|
+
this.image = computed(() => {
|
|
312
|
+
const fit = this.#fit();
|
|
313
|
+
return { x: fit.offsetX, y: fit.offsetY, width: fit.width, height: fit.height };
|
|
314
|
+
}, /* @ts-ignore */
|
|
315
|
+
...(ngDevMode ? [{ debugName: "image" }] : /* istanbul ignore next */ []));
|
|
316
|
+
/** Рамка в пикселях поля */
|
|
317
|
+
this.frameBox = computed(() => frameInField(this.#frame(), this.#fit()), /* @ts-ignore */
|
|
318
|
+
...(ngDevMode ? [{ debugName: "frameBox" }] : /* istanbul ignore next */ []));
|
|
319
|
+
/** Подсказка пустого поля; пусто — подпись кита `uiImageCropperPlaceholder` */
|
|
320
|
+
this.placeholder = input('', /* @ts-ignore */
|
|
321
|
+
...(ngDevMode ? [{ debugName: "placeholder" }] : /* istanbul ignore next */ []));
|
|
322
|
+
/** Исходник: файл, который надо обрезать; пусто — поле с подсказкой */
|
|
323
|
+
this.file = input(null, /* @ts-ignore */
|
|
324
|
+
...(ngDevMode ? [{ debugName: "file" }] : /* istanbul ignore next */ []));
|
|
325
|
+
/** Пропорция рамки, ширина к высоте; пусто — рамка свободная */
|
|
326
|
+
this.ratio = input(null, { ...(ngDevMode ? { debugName: "ratio" } : /* istanbul ignore next */ {}), transform: optionalNumber });
|
|
327
|
+
/** Круглый вид: маска на экране и пропорция один к одному; результат — квадрат */
|
|
328
|
+
this.round = input(false, { ...(ngDevMode ? { debugName: "round" } : /* istanbul ignore next */ {}), transform: booleanAttribute });
|
|
329
|
+
/** Наименьший размер рамки в пикселях исходника */
|
|
330
|
+
this.minSize = input(DEFAULT_MIN_SIZE, { ...(ngDevMode ? { debugName: "minSize" } : /* istanbul ignore next */ {}), transform: (value) => numberAttribute(value, DEFAULT_MIN_SIZE) });
|
|
331
|
+
/** Формат результата; пусто — формат исходника, png, когда он не из трёх */
|
|
332
|
+
this.format = input(null, /* @ts-ignore */
|
|
333
|
+
...(ngDevMode ? [{ debugName: "format" }] : /* istanbul ignore next */ []));
|
|
334
|
+
/** Качество результата в процентах — для jpeg и webp */
|
|
335
|
+
this.quality = input(RT_IMAGE_CROPPER_QUALITY, { ...(ngDevMode ? { debugName: "quality" } : /* istanbul ignore next */ {}), transform: (value) => numberAttribute(value, RT_IMAGE_CROPPER_QUALITY) });
|
|
336
|
+
/** Недоступна: рамка видна, но не меняется ни указателем, ни клавишами */
|
|
337
|
+
this.disabled = input(false, { ...(ngDevMode ? { debugName: "disabled" } : /* istanbul ignore next */ {}), transform: booleanAttribute });
|
|
338
|
+
/** Файл, вырезанный рамкой: после прочтения исходника и после каждого законченного изменения */
|
|
339
|
+
this.cropped = output();
|
|
340
|
+
/** Исходник не прочитался */
|
|
341
|
+
this.loadFailed = output();
|
|
342
|
+
effect(() => {
|
|
343
|
+
const file = this.file();
|
|
344
|
+
untracked(() => this.#load(file));
|
|
345
|
+
});
|
|
346
|
+
effect(() => {
|
|
347
|
+
const ratio = this.#ratio();
|
|
348
|
+
untracked(() => {
|
|
349
|
+
if (this.state() === 'ready') {
|
|
350
|
+
this.#frame.set(initialFrame(this.#source(), ratio));
|
|
351
|
+
this.#emitResult();
|
|
352
|
+
}
|
|
353
|
+
});
|
|
354
|
+
});
|
|
355
|
+
afterNextRender(() => this.#observe(this.field().nativeElement));
|
|
356
|
+
this.#destroyRef.onDestroy(() => this.#revoke());
|
|
357
|
+
}
|
|
358
|
+
onPointerDown(event, handle) {
|
|
359
|
+
if (this.disabled() || this.#drag !== null || (event.pointerType === 'mouse' && event.button !== 0)) {
|
|
360
|
+
return;
|
|
361
|
+
}
|
|
362
|
+
event.preventDefault();
|
|
363
|
+
event.stopPropagation();
|
|
364
|
+
const target = event.currentTarget;
|
|
365
|
+
if (target instanceof this.#window.HTMLElement && typeof target.setPointerCapture === 'function') {
|
|
366
|
+
target.setPointerCapture(event.pointerId);
|
|
367
|
+
}
|
|
368
|
+
this.#drag = { pointerId: event.pointerId, startX: event.clientX, startY: event.clientY, startFrame: this.#frame(), handle };
|
|
369
|
+
}
|
|
370
|
+
onPointerMove(event) {
|
|
371
|
+
const drag = this.#drag;
|
|
372
|
+
if (drag === null || drag.pointerId !== event.pointerId) {
|
|
373
|
+
return;
|
|
374
|
+
}
|
|
375
|
+
event.preventDefault();
|
|
376
|
+
event.stopPropagation();
|
|
377
|
+
const delta = fieldDelta(event.clientX - drag.startX, event.clientY - drag.startY, this.#fit().scale);
|
|
378
|
+
this.#frame.set(this.#change(drag.startFrame, drag.handle, delta));
|
|
379
|
+
}
|
|
380
|
+
onPointerUp(event) {
|
|
381
|
+
const drag = this.#drag;
|
|
382
|
+
if (drag === null || drag.pointerId !== event.pointerId) {
|
|
383
|
+
return;
|
|
384
|
+
}
|
|
385
|
+
event.stopPropagation();
|
|
386
|
+
this.#drag = null;
|
|
387
|
+
const target = event.currentTarget;
|
|
388
|
+
if (target instanceof this.#window.HTMLElement && typeof target.releasePointerCapture === 'function') {
|
|
389
|
+
target.releasePointerCapture(event.pointerId);
|
|
390
|
+
}
|
|
391
|
+
if (!sameRect(drag.startFrame, this.#frame())) {
|
|
392
|
+
this.#emitResult();
|
|
393
|
+
}
|
|
394
|
+
}
|
|
395
|
+
onKeyDown(event, handle) {
|
|
396
|
+
if (this.disabled()) {
|
|
397
|
+
return;
|
|
398
|
+
}
|
|
399
|
+
const delta = keyDelta(event.key, event.shiftKey, this.#fit().scale);
|
|
400
|
+
if (delta === null) {
|
|
401
|
+
return;
|
|
402
|
+
}
|
|
403
|
+
event.preventDefault();
|
|
404
|
+
event.stopPropagation();
|
|
405
|
+
const before = this.#frame();
|
|
406
|
+
const next = this.#change(before, handle, delta);
|
|
407
|
+
if (!sameRect(before, next)) {
|
|
408
|
+
this.#frame.set(next);
|
|
409
|
+
this.#emitResult();
|
|
410
|
+
}
|
|
411
|
+
}
|
|
412
|
+
/** Одна точка для указателя и клавиш: внутри рамки — сдвиг, на ручке — растяжение */
|
|
413
|
+
#change(frame, handle, delta) {
|
|
414
|
+
return handle === null
|
|
415
|
+
? moveFrame(frame, delta, this.#source())
|
|
416
|
+
: resizeFrame(frame, handle, delta, this.#source(), this.#ratio(), this.minSize());
|
|
417
|
+
}
|
|
418
|
+
#load(file) {
|
|
419
|
+
this.#revoke();
|
|
420
|
+
this.#image = null;
|
|
421
|
+
this.#pending = null;
|
|
422
|
+
this.#drag = null;
|
|
423
|
+
this.#resultTicket++;
|
|
424
|
+
if (file === null || !this.#platform.isPlatformBrowser) {
|
|
425
|
+
this.state.set('empty');
|
|
426
|
+
return;
|
|
427
|
+
}
|
|
428
|
+
this.#sourceType = file.type;
|
|
429
|
+
this.#sourceName = file instanceof this.#window.File ? file.name : '';
|
|
430
|
+
const url = this.#window.URL.createObjectURL(file);
|
|
431
|
+
const image = new this.#window.Image();
|
|
432
|
+
this.#pending = image;
|
|
433
|
+
this.url.set(url);
|
|
434
|
+
this.state.set('loading');
|
|
435
|
+
image.onload = () => {
|
|
436
|
+
if (this.#pending === image) {
|
|
437
|
+
this.#pending = null;
|
|
438
|
+
this.#ready(image);
|
|
439
|
+
}
|
|
440
|
+
};
|
|
441
|
+
image.onerror = () => {
|
|
442
|
+
if (this.#pending === image) {
|
|
443
|
+
this.#pending = null;
|
|
444
|
+
this.#refuse();
|
|
445
|
+
}
|
|
446
|
+
};
|
|
447
|
+
image.src = url;
|
|
448
|
+
}
|
|
449
|
+
#ready(image) {
|
|
450
|
+
if (image.naturalWidth <= 0 || image.naturalHeight <= 0) {
|
|
451
|
+
this.#refuse();
|
|
452
|
+
return;
|
|
453
|
+
}
|
|
454
|
+
this.#image = image;
|
|
455
|
+
this.#source.set({ width: image.naturalWidth, height: image.naturalHeight });
|
|
456
|
+
this.#frame.set(initialFrame(this.#source(), this.#ratio()));
|
|
457
|
+
this.state.set('ready');
|
|
458
|
+
this.#emitResult();
|
|
459
|
+
}
|
|
460
|
+
#refuse() {
|
|
461
|
+
this.state.set('refusal');
|
|
462
|
+
this.loadFailed.emit();
|
|
463
|
+
}
|
|
464
|
+
#revoke() {
|
|
465
|
+
const url = this.url();
|
|
466
|
+
if (url !== null) {
|
|
467
|
+
this.#window.URL.revokeObjectURL(url);
|
|
468
|
+
this.url.set(null);
|
|
469
|
+
}
|
|
470
|
+
}
|
|
471
|
+
#observe(field) {
|
|
472
|
+
const measure = () => this.#fieldSize.set({ width: field.clientWidth, height: field.clientHeight });
|
|
473
|
+
measure();
|
|
474
|
+
if (typeof this.#window.ResizeObserver !== 'function') {
|
|
475
|
+
return;
|
|
476
|
+
}
|
|
477
|
+
const observer = new this.#window.ResizeObserver(measure);
|
|
478
|
+
observer.observe(field);
|
|
479
|
+
this.#destroyRef.onDestroy(() => observer.disconnect());
|
|
480
|
+
}
|
|
481
|
+
/** Вырезает рамку холстом и отдаёт файл; ответ по устаревшей рамке не выходит */
|
|
482
|
+
#emitResult() {
|
|
483
|
+
const image = this.#image;
|
|
484
|
+
if (image === null) {
|
|
485
|
+
return;
|
|
486
|
+
}
|
|
487
|
+
this.#resultTicket++;
|
|
488
|
+
const ticket = this.#resultTicket;
|
|
489
|
+
const area = cropArea(this.#frame(), this.#source());
|
|
490
|
+
const canvas = this.#document.createElement('canvas');
|
|
491
|
+
canvas.width = area.width;
|
|
492
|
+
canvas.height = area.height;
|
|
493
|
+
const context = canvas.getContext('2d');
|
|
494
|
+
if (context === null) {
|
|
495
|
+
return;
|
|
496
|
+
}
|
|
497
|
+
context.drawImage(image, area.x, area.y, area.width, area.height, 0, 0, area.width, area.height);
|
|
498
|
+
const type = resultType(this.format(), this.#sourceType);
|
|
499
|
+
canvas.toBlob((blob) => {
|
|
500
|
+
if (blob === null || ticket !== this.#resultTicket) {
|
|
501
|
+
return;
|
|
502
|
+
}
|
|
503
|
+
const file = new this.#window.File([blob], resultFileName(this.#sourceName, type), { type });
|
|
504
|
+
this.cropped.emit({ file, frame: area });
|
|
505
|
+
}, type, resultQuality(this.quality()));
|
|
506
|
+
}
|
|
507
|
+
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "22.1.6", ngImport: i0, type: RtImageCropperComponent, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
|
|
508
|
+
static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "22.1.6", type: RtImageCropperComponent, isStandalone: true, selector: "rt-image-cropper", inputs: { placeholder: { classPropertyName: "placeholder", publicName: "placeholder", isSignal: true, isRequired: false, transformFunction: null }, file: { classPropertyName: "file", publicName: "file", isSignal: true, isRequired: false, transformFunction: null }, ratio: { classPropertyName: "ratio", publicName: "ratio", isSignal: true, isRequired: false, transformFunction: null }, round: { classPropertyName: "round", publicName: "round", isSignal: true, isRequired: false, transformFunction: null }, minSize: { classPropertyName: "minSize", publicName: "minSize", isSignal: true, isRequired: false, transformFunction: null }, format: { classPropertyName: "format", publicName: "format", isSignal: true, isRequired: false, transformFunction: null }, quality: { classPropertyName: "quality", publicName: "quality", isSignal: true, isRequired: false, transformFunction: null }, disabled: { classPropertyName: "disabled", publicName: "disabled", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { cropped: "cropped", loadFailed: "loadFailed" }, host: { properties: { "class.rt-image-cropper--round": "round()", "class.rt-image-cropper--disabled": "disabled()", "style.--rt-image-cropper-image-x": "image().x + 'px'", "style.--rt-image-cropper-image-y": "image().y + 'px'", "style.--rt-image-cropper-image-width": "image().width + 'px'", "style.--rt-image-cropper-image-height": "image().height + 'px'", "style.--rt-image-cropper-frame-x": "frameBox().x + 'px'", "style.--rt-image-cropper-frame-y": "frameBox().y + 'px'", "style.--rt-image-cropper-frame-width": "frameBox().width + 'px'", "style.--rt-image-cropper-frame-height": "frameBox().height + 'px'" }, classAttribute: "rt-image-cropper" }, viewQueries: [{ propertyName: "field", first: true, predicate: ["field"], descendants: true, isSignal: true }], ngImport: i0, template: "<ng-container rtBlock=\"rt-image-cropper\">\n <div #field rtElem=\"field\" qa-dataid=\"image-cropper-field\">\n @switch (state()) {\n @case ('empty') {\n <p rtElem=\"placeholder\" qa-dataid=\"image-cropper-placeholder\">{{ placeholderText() }}</p>\n }\n @case ('loading') {\n <rt-spinner rtElem=\"spinner\" qa-dataid=\"image-cropper-spinner\" />\n }\n @case ('refusal') {\n <p rtElem=\"refusal\" qa-dataid=\"image-cropper-refusal\">{{ t().uiImageCropperRefusal }}</p>\n }\n @case ('ready') {\n <img rtElem=\"image\" qa-dataid=\"image-cropper-image\" alt=\"\" draggable=\"false\" [src]=\"url()\" />\n <div\n rtElem=\"frame\"\n qa-dataid=\"image-cropper-frame\"\n role=\"group\"\n [attr.aria-label]=\"t().uiImageCropperFrame\"\n [attr.aria-disabled]=\"disabled() || null\"\n [attr.tabindex]=\"disabled() ? -1 : 0\"\n (pointerdown)=\"onPointerDown($event, null)\"\n (pointermove)=\"onPointerMove($event)\"\n (pointerup)=\"onPointerUp($event)\"\n (pointercancel)=\"onPointerUp($event)\"\n (keydown)=\"onKeyDown($event, null)\">\n @for (handle of handles; track handle) {\n <span\n rtElem=\"handle\"\n role=\"button\"\n [attr.qa-dataid]=\"'image-cropper-handle-' + handle\"\n [rtMod]=\"{ side: handle }\"\n [attr.aria-label]=\"t()[handleLabels[handle]]\"\n [attr.aria-disabled]=\"disabled() || null\"\n [attr.tabindex]=\"disabled() ? -1 : 0\"\n (pointerdown)=\"onPointerDown($event, handle)\"\n (pointermove)=\"onPointerMove($event)\"\n (pointerup)=\"onPointerUp($event)\"\n (pointercancel)=\"onPointerUp($event)\"\n (keydown)=\"onKeyDown($event, handle)\"></span>\n }\n </div>\n }\n }\n </div>\n</ng-container>\n", styles: ["@charset \"UTF-8\";@layer rt-kit.components{.rt-image-cropper{--rt-image-cropper-height: calc(var(--rt-size-20) * 4);--rt-image-cropper-radius: var(--rt-radius-md);--rt-image-cropper-frame-radius: var(--rt-radius-none);--rt-image-cropper-field-bg: var(--rt-color-bg-subtle);--rt-image-cropper-shade: var(--rt-overlay-black-50);--rt-image-cropper-rim-width: var(--rt-border-width-thin);--rt-image-cropper-rim-color: var(--rt-overlay-white-50);--rt-image-cropper-dash-style: none;--rt-image-cropper-dash-color: transparent;--rt-image-cropper-dash-opacity: 1;--rt-image-cropper-handle-size: var(--rt-size-3);--rt-image-cropper-handle-bg: var(--rt-color-action-on-primary);--rt-image-cropper-handle-border: var(--rt-color-border-strong);--rt-image-cropper-focus-shadow: var(--rt-shadow-focus-ring);--rt-image-cropper-text-color: var(--rt-color-text-muted);--rt-image-cropper-disabled-opacity: .5;--rt-image-cropper-image-x: 0;--rt-image-cropper-image-y: 0;--rt-image-cropper-image-width: 0;--rt-image-cropper-image-height: 0;--rt-image-cropper-frame-x: 0;--rt-image-cropper-frame-y: 0;--rt-image-cropper-frame-width: 0;--rt-image-cropper-frame-height: 0;display:block;width:100%}.rt-image-cropper__field{position:relative;overflow:hidden;height:var(--rt-image-cropper-height);border-radius:var(--rt-image-cropper-radius);background:var(--rt-image-cropper-field-bg);-webkit-user-select:none;user-select:none}.rt-image-cropper__spinner{position:absolute;inset:50% auto auto 50%;translate:-50% -50%}.rt-image-cropper__placeholder,.rt-image-cropper__refusal{position:absolute;display:flex;align-items:center;justify-content:center;padding:var(--rt-space-md);margin:0;color:var(--rt-image-cropper-text-color);inset:0;text-align:center}.rt-image-cropper__image{position:absolute;top:var(--rt-image-cropper-image-y);left:var(--rt-image-cropper-image-x);width:var(--rt-image-cropper-image-width);max-width:none;height:var(--rt-image-cropper-image-height);image-orientation:from-image;pointer-events:none}.rt-image-cropper__frame{position:absolute;top:var(--rt-image-cropper-frame-y);left:var(--rt-image-cropper-frame-x);width:var(--rt-image-cropper-frame-width);height:var(--rt-image-cropper-frame-height);box-sizing:border-box;border:var(--rt-image-cropper-rim-width) solid var(--rt-image-cropper-rim-color);border-radius:var(--rt-image-cropper-frame-radius);cursor:move;outline:100vmax solid var(--rt-image-cropper-shade);touch-action:none}.rt-image-cropper__frame:after{position:absolute;border:var(--rt-image-cropper-rim-width) var(--rt-image-cropper-dash-style) var(--rt-image-cropper-dash-color);border-radius:inherit;content:\"\";inset:calc(-1 * var(--rt-image-cropper-rim-width));opacity:var(--rt-image-cropper-dash-opacity);pointer-events:none}.rt-image-cropper__frame:focus-visible{box-shadow:var(--rt-image-cropper-focus-shadow)}.rt-image-cropper__handle{position:absolute;width:var(--rt-image-cropper-handle-size);height:var(--rt-image-cropper-handle-size);box-sizing:border-box;border:var(--rt-image-cropper-rim-width) solid var(--rt-image-cropper-handle-border);background:var(--rt-image-cropper-handle-bg);touch-action:none}.rt-image-cropper__handle:focus-visible{box-shadow:var(--rt-image-cropper-focus-shadow);outline:none}.rt-image-cropper__handle--side--nw{top:0;left:0;cursor:nwse-resize}.rt-image-cropper__handle--side--n{top:0;left:50%;cursor:ns-resize;translate:-50% 0}.rt-image-cropper__handle--side--ne{top:0;left:100%;cursor:nesw-resize;translate:-100% 0}.rt-image-cropper__handle--side--e{top:50%;left:100%;cursor:ew-resize;translate:-100% -50%}.rt-image-cropper__handle--side--se{top:100%;left:100%;cursor:nwse-resize;translate:-100% -100%}.rt-image-cropper__handle--side--s{top:100%;left:50%;cursor:ns-resize;translate:-50% -100%}.rt-image-cropper__handle--side--sw{top:100%;left:0;cursor:nesw-resize;translate:0 -100%}.rt-image-cropper__handle--side--w{top:50%;left:0;cursor:ew-resize;translate:0 -50%}:is(.rt-preset-material,[data-preset=material]) .rt-image-cropper{--rt-image-cropper-radius: var(--rt-radius-none);--rt-image-cropper-field-bg: transparent;--rt-image-cropper-shade: var(--rt-overlay-white-25);--rt-image-cropper-dash-style: dashed;--rt-image-cropper-dash-color: var(--rt-mat-dark-40);--rt-image-cropper-dash-opacity: .75;--rt-image-cropper-handle-size: var(--rt-size-2);--rt-image-cropper-handle-bg: var(--rt-mat-dark-40);--rt-image-cropper-handle-border: var(--rt-overlay-white-50)}@media(pointer:coarse){:is(.rt-preset-material,[data-preset=material]) .rt-image-cropper{--rt-image-cropper-handle-size: var(--rt-size-6)}}.rt-image-cropper--round{--rt-image-cropper-frame-radius: var(--rt-radius-full)}.rt-image-cropper--disabled .rt-image-cropper__frame,.rt-image-cropper--disabled .rt-image-cropper__handle{cursor:default}.rt-image-cropper--disabled .rt-image-cropper__handle,.rt-image-cropper--disabled .rt-image-cropper__image{opacity:var(--rt-image-cropper-disabled-opacity)}@media(pointer:coarse){.rt-image-cropper{--rt-image-cropper-handle-size: var(--rt-size-6)}}}\n"], dependencies: [{ kind: "directive", type:
|
|
509
|
+
// standalone components / directives
|
|
510
|
+
BlockDirective, selector: "[rtBlock]", inputs: ["rtMod"] }, { kind: "directive", type: ElemDirective, selector: "[rtElem]", inputs: ["rtMod"] }, { kind: "directive", type: ModDirective, selector: "[rtMod]" }, { kind: "component", type: RtSpinnerComponent, selector: "rt-spinner", inputs: ["diameter", "color", "appearance", "overlay", "backdrop", "plate"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush, encapsulation: i0.ViewEncapsulation.None }); }
|
|
511
|
+
}
|
|
512
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.1.6", ngImport: i0, type: RtImageCropperComponent, decorators: [{
|
|
513
|
+
type: Component,
|
|
514
|
+
args: [{ selector: 'rt-image-cropper', changeDetection: ChangeDetectionStrategy.OnPush, encapsulation: ViewEncapsulation.None, imports: [
|
|
515
|
+
// standalone components / directives
|
|
516
|
+
BlockDirective,
|
|
517
|
+
ElemDirective,
|
|
518
|
+
ModDirective,
|
|
519
|
+
RtSpinnerComponent,
|
|
520
|
+
], host: {
|
|
521
|
+
class: BEM_BLOCK,
|
|
522
|
+
'[class.rt-image-cropper--round]': 'round()',
|
|
523
|
+
'[class.rt-image-cropper--disabled]': 'disabled()',
|
|
524
|
+
'[style.--rt-image-cropper-image-x]': "image().x + 'px'",
|
|
525
|
+
'[style.--rt-image-cropper-image-y]': "image().y + 'px'",
|
|
526
|
+
'[style.--rt-image-cropper-image-width]': "image().width + 'px'",
|
|
527
|
+
'[style.--rt-image-cropper-image-height]': "image().height + 'px'",
|
|
528
|
+
'[style.--rt-image-cropper-frame-x]': "frameBox().x + 'px'",
|
|
529
|
+
'[style.--rt-image-cropper-frame-y]': "frameBox().y + 'px'",
|
|
530
|
+
'[style.--rt-image-cropper-frame-width]': "frameBox().width + 'px'",
|
|
531
|
+
'[style.--rt-image-cropper-frame-height]': "frameBox().height + 'px'",
|
|
532
|
+
}, template: "<ng-container rtBlock=\"rt-image-cropper\">\n <div #field rtElem=\"field\" qa-dataid=\"image-cropper-field\">\n @switch (state()) {\n @case ('empty') {\n <p rtElem=\"placeholder\" qa-dataid=\"image-cropper-placeholder\">{{ placeholderText() }}</p>\n }\n @case ('loading') {\n <rt-spinner rtElem=\"spinner\" qa-dataid=\"image-cropper-spinner\" />\n }\n @case ('refusal') {\n <p rtElem=\"refusal\" qa-dataid=\"image-cropper-refusal\">{{ t().uiImageCropperRefusal }}</p>\n }\n @case ('ready') {\n <img rtElem=\"image\" qa-dataid=\"image-cropper-image\" alt=\"\" draggable=\"false\" [src]=\"url()\" />\n <div\n rtElem=\"frame\"\n qa-dataid=\"image-cropper-frame\"\n role=\"group\"\n [attr.aria-label]=\"t().uiImageCropperFrame\"\n [attr.aria-disabled]=\"disabled() || null\"\n [attr.tabindex]=\"disabled() ? -1 : 0\"\n (pointerdown)=\"onPointerDown($event, null)\"\n (pointermove)=\"onPointerMove($event)\"\n (pointerup)=\"onPointerUp($event)\"\n (pointercancel)=\"onPointerUp($event)\"\n (keydown)=\"onKeyDown($event, null)\">\n @for (handle of handles; track handle) {\n <span\n rtElem=\"handle\"\n role=\"button\"\n [attr.qa-dataid]=\"'image-cropper-handle-' + handle\"\n [rtMod]=\"{ side: handle }\"\n [attr.aria-label]=\"t()[handleLabels[handle]]\"\n [attr.aria-disabled]=\"disabled() || null\"\n [attr.tabindex]=\"disabled() ? -1 : 0\"\n (pointerdown)=\"onPointerDown($event, handle)\"\n (pointermove)=\"onPointerMove($event)\"\n (pointerup)=\"onPointerUp($event)\"\n (pointercancel)=\"onPointerUp($event)\"\n (keydown)=\"onKeyDown($event, handle)\"></span>\n }\n </div>\n }\n }\n </div>\n</ng-container>\n", styles: ["@charset \"UTF-8\";@layer rt-kit.components{.rt-image-cropper{--rt-image-cropper-height: calc(var(--rt-size-20) * 4);--rt-image-cropper-radius: var(--rt-radius-md);--rt-image-cropper-frame-radius: var(--rt-radius-none);--rt-image-cropper-field-bg: var(--rt-color-bg-subtle);--rt-image-cropper-shade: var(--rt-overlay-black-50);--rt-image-cropper-rim-width: var(--rt-border-width-thin);--rt-image-cropper-rim-color: var(--rt-overlay-white-50);--rt-image-cropper-dash-style: none;--rt-image-cropper-dash-color: transparent;--rt-image-cropper-dash-opacity: 1;--rt-image-cropper-handle-size: var(--rt-size-3);--rt-image-cropper-handle-bg: var(--rt-color-action-on-primary);--rt-image-cropper-handle-border: var(--rt-color-border-strong);--rt-image-cropper-focus-shadow: var(--rt-shadow-focus-ring);--rt-image-cropper-text-color: var(--rt-color-text-muted);--rt-image-cropper-disabled-opacity: .5;--rt-image-cropper-image-x: 0;--rt-image-cropper-image-y: 0;--rt-image-cropper-image-width: 0;--rt-image-cropper-image-height: 0;--rt-image-cropper-frame-x: 0;--rt-image-cropper-frame-y: 0;--rt-image-cropper-frame-width: 0;--rt-image-cropper-frame-height: 0;display:block;width:100%}.rt-image-cropper__field{position:relative;overflow:hidden;height:var(--rt-image-cropper-height);border-radius:var(--rt-image-cropper-radius);background:var(--rt-image-cropper-field-bg);-webkit-user-select:none;user-select:none}.rt-image-cropper__spinner{position:absolute;inset:50% auto auto 50%;translate:-50% -50%}.rt-image-cropper__placeholder,.rt-image-cropper__refusal{position:absolute;display:flex;align-items:center;justify-content:center;padding:var(--rt-space-md);margin:0;color:var(--rt-image-cropper-text-color);inset:0;text-align:center}.rt-image-cropper__image{position:absolute;top:var(--rt-image-cropper-image-y);left:var(--rt-image-cropper-image-x);width:var(--rt-image-cropper-image-width);max-width:none;height:var(--rt-image-cropper-image-height);image-orientation:from-image;pointer-events:none}.rt-image-cropper__frame{position:absolute;top:var(--rt-image-cropper-frame-y);left:var(--rt-image-cropper-frame-x);width:var(--rt-image-cropper-frame-width);height:var(--rt-image-cropper-frame-height);box-sizing:border-box;border:var(--rt-image-cropper-rim-width) solid var(--rt-image-cropper-rim-color);border-radius:var(--rt-image-cropper-frame-radius);cursor:move;outline:100vmax solid var(--rt-image-cropper-shade);touch-action:none}.rt-image-cropper__frame:after{position:absolute;border:var(--rt-image-cropper-rim-width) var(--rt-image-cropper-dash-style) var(--rt-image-cropper-dash-color);border-radius:inherit;content:\"\";inset:calc(-1 * var(--rt-image-cropper-rim-width));opacity:var(--rt-image-cropper-dash-opacity);pointer-events:none}.rt-image-cropper__frame:focus-visible{box-shadow:var(--rt-image-cropper-focus-shadow)}.rt-image-cropper__handle{position:absolute;width:var(--rt-image-cropper-handle-size);height:var(--rt-image-cropper-handle-size);box-sizing:border-box;border:var(--rt-image-cropper-rim-width) solid var(--rt-image-cropper-handle-border);background:var(--rt-image-cropper-handle-bg);touch-action:none}.rt-image-cropper__handle:focus-visible{box-shadow:var(--rt-image-cropper-focus-shadow);outline:none}.rt-image-cropper__handle--side--nw{top:0;left:0;cursor:nwse-resize}.rt-image-cropper__handle--side--n{top:0;left:50%;cursor:ns-resize;translate:-50% 0}.rt-image-cropper__handle--side--ne{top:0;left:100%;cursor:nesw-resize;translate:-100% 0}.rt-image-cropper__handle--side--e{top:50%;left:100%;cursor:ew-resize;translate:-100% -50%}.rt-image-cropper__handle--side--se{top:100%;left:100%;cursor:nwse-resize;translate:-100% -100%}.rt-image-cropper__handle--side--s{top:100%;left:50%;cursor:ns-resize;translate:-50% -100%}.rt-image-cropper__handle--side--sw{top:100%;left:0;cursor:nesw-resize;translate:0 -100%}.rt-image-cropper__handle--side--w{top:50%;left:0;cursor:ew-resize;translate:0 -50%}:is(.rt-preset-material,[data-preset=material]) .rt-image-cropper{--rt-image-cropper-radius: var(--rt-radius-none);--rt-image-cropper-field-bg: transparent;--rt-image-cropper-shade: var(--rt-overlay-white-25);--rt-image-cropper-dash-style: dashed;--rt-image-cropper-dash-color: var(--rt-mat-dark-40);--rt-image-cropper-dash-opacity: .75;--rt-image-cropper-handle-size: var(--rt-size-2);--rt-image-cropper-handle-bg: var(--rt-mat-dark-40);--rt-image-cropper-handle-border: var(--rt-overlay-white-50)}@media(pointer:coarse){:is(.rt-preset-material,[data-preset=material]) .rt-image-cropper{--rt-image-cropper-handle-size: var(--rt-size-6)}}.rt-image-cropper--round{--rt-image-cropper-frame-radius: var(--rt-radius-full)}.rt-image-cropper--disabled .rt-image-cropper__frame,.rt-image-cropper--disabled .rt-image-cropper__handle{cursor:default}.rt-image-cropper--disabled .rt-image-cropper__handle,.rt-image-cropper--disabled .rt-image-cropper__image{opacity:var(--rt-image-cropper-disabled-opacity)}@media(pointer:coarse){.rt-image-cropper{--rt-image-cropper-handle-size: var(--rt-size-6)}}}\n"] }]
|
|
533
|
+
}], ctorParameters: () => [], propDecorators: { field: [{ type: i0.ViewChild, args: ['field', { isSignal: true }] }], placeholder: [{ type: i0.Input, args: [{ isSignal: true, alias: "placeholder", required: false }] }], file: [{ type: i0.Input, args: [{ isSignal: true, alias: "file", required: false }] }], ratio: [{ type: i0.Input, args: [{ isSignal: true, alias: "ratio", required: false }] }], round: [{ type: i0.Input, args: [{ isSignal: true, alias: "round", required: false }] }], minSize: [{ type: i0.Input, args: [{ isSignal: true, alias: "minSize", required: false }] }], format: [{ type: i0.Input, args: [{ isSignal: true, alias: "format", required: false }] }], quality: [{ type: i0.Input, args: [{ isSignal: true, alias: "quality", required: false }] }], disabled: [{ type: i0.Input, args: [{ isSignal: true, alias: "disabled", required: false }] }], cropped: [{ type: i0.Output, args: ["cropped"] }], loadFailed: [{ type: i0.Output, args: ["loadFailed"] }] } });
|
|
534
|
+
|
|
535
|
+
/**
|
|
536
|
+
* Generated bundle index. Do not edit.
|
|
537
|
+
*/
|
|
538
|
+
|
|
539
|
+
export { RT_IMAGE_CROPPER_HANDLES, RT_IMAGE_CROPPER_KEY_STEP, RT_IMAGE_CROPPER_KEY_STEP_LARGE, RT_IMAGE_CROPPER_QUALITY, RtImageCropperComponent, cropArea, fieldDelta, fitSource, frameInField, frameRatio, handleDirection, initialFrame, keyDelta, moveFrame, resizeFrame, resultFileName, resultQuality, resultType };
|
|
540
|
+
//# sourceMappingURL=rt-tools-ui-kit-v2-image-cropper.mjs.map
|