@slotted/angular 0.0.0-stage → 0.1.0-beta.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/LICENSE +21 -0
- package/README.md +51 -2
- package/docs/AGENTS.snippet.md +10 -0
- package/docs/accordion.json +345 -0
- package/docs/accordion.md +207 -0
- package/docs/action-bar.json +421 -0
- package/docs/action-bar.md +364 -0
- package/docs/action-sheet.json +210 -0
- package/docs/action-sheet.md +19 -0
- package/docs/alert.json +407 -0
- package/docs/alert.md +239 -0
- package/docs/app-shell.examples.md +349 -0
- package/docs/app-shell.json +835 -0
- package/docs/app-shell.md +214 -0
- package/docs/aspect-ratio.json +159 -0
- package/docs/aspect-ratio.md +134 -0
- package/docs/attachment.json +486 -0
- package/docs/attachment.md +253 -0
- package/docs/avatar-group.json +208 -0
- package/docs/avatar-group.md +130 -0
- package/docs/avatar.json +342 -0
- package/docs/avatar.md +142 -0
- package/docs/badge.json +334 -0
- package/docs/badge.md +138 -0
- package/docs/breadcrumb.json +368 -0
- package/docs/breadcrumb.md +237 -0
- package/docs/button-group.json +158 -0
- package/docs/button-group.md +72 -0
- package/docs/button.examples.md +621 -0
- package/docs/button.json +977 -0
- package/docs/button.md +200 -0
- package/docs/calendar.json +592 -0
- package/docs/calendar.md +242 -0
- package/docs/card.json +283 -0
- package/docs/card.md +130 -0
- package/docs/carousel.json +560 -0
- package/docs/carousel.md +357 -0
- package/docs/cascader.json +933 -0
- package/docs/cascader.md +379 -0
- package/docs/chart.examples.md +582 -0
- package/docs/chart.json +1359 -0
- package/docs/chart.md +187 -0
- package/docs/checkbox-group.examples.md +612 -0
- package/docs/checkbox-group.json +395 -0
- package/docs/checkbox-group.md +106 -0
- package/docs/checkbox.examples.md +546 -0
- package/docs/checkbox.json +506 -0
- package/docs/checkbox.md +104 -0
- package/docs/code-block.json +616 -0
- package/docs/code-block.md +303 -0
- package/docs/collapsible.json +456 -0
- package/docs/collapsible.md +261 -0
- package/docs/color-picker.json +523 -0
- package/docs/color-picker.md +201 -0
- package/docs/column-manager.json +486 -0
- package/docs/column-manager.md +277 -0
- package/docs/combobox.examples.md +1732 -0
- package/docs/combobox.json +1250 -0
- package/docs/combobox.md +209 -0
- package/docs/command-palette.json +800 -0
- package/docs/command-palette.md +419 -0
- package/docs/container.json +156 -0
- package/docs/container.md +92 -0
- package/docs/context-menu.json +231 -0
- package/docs/context-menu.md +176 -0
- package/docs/currency-field.examples.md +321 -0
- package/docs/currency-field.json +649 -0
- package/docs/currency-field.md +128 -0
- package/docs/dashboard-grid.json +680 -0
- package/docs/dashboard-grid.md +265 -0
- package/docs/data-grid.examples.md +3064 -0
- package/docs/data-grid.json +1577 -0
- package/docs/data-grid.md +237 -0
- package/docs/data-grid.props.md +81 -0
- package/docs/data-list.json +685 -0
- package/docs/data-list.md +327 -0
- package/docs/date-field.json +490 -0
- package/docs/date-field.md +235 -0
- package/docs/date-picker.examples.md +1226 -0
- package/docs/date-picker.json +696 -0
- package/docs/date-picker.md +121 -0
- package/docs/date-range-picker.examples.md +1300 -0
- package/docs/date-range-picker.json +903 -0
- package/docs/date-range-picker.md +142 -0
- package/docs/datetime-field.json +665 -0
- package/docs/datetime-field.md +337 -0
- package/docs/datetime-picker.examples.md +1269 -0
- package/docs/datetime-picker.json +928 -0
- package/docs/datetime-picker.md +150 -0
- package/docs/datetime-range-picker.examples.md +225 -0
- package/docs/datetime-range-picker.json +1015 -0
- package/docs/datetime-range-picker.md +162 -0
- package/docs/description-list.json +471 -0
- package/docs/description-list.md +268 -0
- package/docs/detail-panel.json +530 -0
- package/docs/detail-panel.md +361 -0
- package/docs/dialog.examples.md +2467 -0
- package/docs/dialog.json +1141 -0
- package/docs/dialog.md +217 -0
- package/docs/dialog.props.md +63 -0
- package/docs/divider.json +148 -0
- package/docs/divider.md +83 -0
- package/docs/drawer.examples.md +1929 -0
- package/docs/drawer.json +753 -0
- package/docs/drawer.md +199 -0
- package/docs/entity-picker.json +946 -0
- package/docs/entity-picker.md +365 -0
- package/docs/event-calendar.examples.md +308 -0
- package/docs/event-calendar.json +1202 -0
- package/docs/event-calendar.md +201 -0
- package/docs/field-group.json +333 -0
- package/docs/field-group.md +181 -0
- package/docs/field.examples.md +676 -0
- package/docs/field.json +528 -0
- package/docs/field.md +127 -0
- package/docs/filter-bar.json +817 -0
- package/docs/filter-bar.md +380 -0
- package/docs/form.json +378 -0
- package/docs/form.md +235 -0
- package/docs/fullscreen.json +395 -0
- package/docs/fullscreen.md +225 -0
- package/docs/grid.json +176 -0
- package/docs/grid.md +74 -0
- package/docs/highlight.json +279 -0
- package/docs/highlight.md +210 -0
- package/docs/hover-card.json +254 -0
- package/docs/hover-card.md +213 -0
- package/docs/icon.json +173 -0
- package/docs/icon.md +101 -0
- package/docs/image.json +476 -0
- package/docs/image.md +254 -0
- package/docs/import-export-center.json +836 -0
- package/docs/import-export-center.md +345 -0
- package/docs/index.md +141 -0
- package/docs/inline-message.json +312 -0
- package/docs/inline-message.md +191 -0
- package/docs/inline.json +149 -0
- package/docs/inline.md +72 -0
- package/docs/kbd.json +350 -0
- package/docs/kbd.md +210 -0
- package/docs/link.json +264 -0
- package/docs/link.md +167 -0
- package/docs/list-item.json +463 -0
- package/docs/list-item.md +236 -0
- package/docs/list.json +321 -0
- package/docs/list.md +185 -0
- package/docs/listbox.json +807 -0
- package/docs/listbox.md +413 -0
- package/docs/loading-overlay.json +440 -0
- package/docs/loading-overlay.md +248 -0
- package/docs/markdown.json +461 -0
- package/docs/markdown.md +266 -0
- package/docs/menu.examples.md +1651 -0
- package/docs/menu.json +922 -0
- package/docs/menu.md +155 -0
- package/docs/menubar.json +292 -0
- package/docs/menubar.md +173 -0
- package/docs/message-scroller.json +401 -0
- package/docs/message-scroller.md +212 -0
- package/docs/message.json +862 -0
- package/docs/message.md +473 -0
- package/docs/multi-select.examples.md +1922 -0
- package/docs/multi-select.json +1314 -0
- package/docs/multi-select.md +213 -0
- package/docs/navigation-menu.json +529 -0
- package/docs/navigation-menu.md +329 -0
- package/docs/notification-center.json +664 -0
- package/docs/notification-center.md +372 -0
- package/docs/number-field.examples.md +1078 -0
- package/docs/number-field.json +668 -0
- package/docs/number-field.md +137 -0
- package/docs/otp-input.json +479 -0
- package/docs/otp-input.md +291 -0
- package/docs/page-header.json +574 -0
- package/docs/page-header.md +338 -0
- package/docs/page.json +332 -0
- package/docs/page.md +184 -0
- package/docs/pagination.json +434 -0
- package/docs/pagination.md +238 -0
- package/docs/popover.examples.md +1235 -0
- package/docs/popover.json +656 -0
- package/docs/popover.md +199 -0
- package/docs/progress-indicator.json +501 -0
- package/docs/progress-indicator.md +329 -0
- package/docs/prompt-composer.json +498 -0
- package/docs/prompt-composer.md +278 -0
- package/docs/prose.json +357 -0
- package/docs/prose.md +226 -0
- package/docs/radio-group.examples.md +626 -0
- package/docs/radio-group.json +541 -0
- package/docs/radio-group.md +112 -0
- package/docs/rating.json +1053 -0
- package/docs/rating.md +435 -0
- package/docs/result-state.json +376 -0
- package/docs/result-state.md +286 -0
- package/docs/saved-views.json +384 -0
- package/docs/saved-views.md +242 -0
- package/docs/scroll-area.json +120 -0
- package/docs/scroll-area.md +8 -0
- package/docs/section.json +344 -0
- package/docs/section.md +208 -0
- package/docs/segmented-control.json +429 -0
- package/docs/segmented-control.md +240 -0
- package/docs/select.examples.md +1214 -0
- package/docs/select.json +1147 -0
- package/docs/select.md +199 -0
- package/docs/side-navigation.json +632 -0
- package/docs/side-navigation.md +430 -0
- package/docs/skeleton.json +358 -0
- package/docs/skeleton.md +223 -0
- package/docs/slider.json +522 -0
- package/docs/slider.md +261 -0
- package/docs/sparkline.json +426 -0
- package/docs/sparkline.md +206 -0
- package/docs/split-button.json +361 -0
- package/docs/split-button.md +275 -0
- package/docs/splitter.json +142 -0
- package/docs/splitter.md +14 -0
- package/docs/stack.json +135 -0
- package/docs/stack.md +74 -0
- package/docs/stat-card.json +529 -0
- package/docs/stat-card.md +270 -0
- package/docs/status-indicator.json +314 -0
- package/docs/status-indicator.md +197 -0
- package/docs/stepper.json +451 -0
- package/docs/stepper.md +250 -0
- package/docs/switch.json +451 -0
- package/docs/switch.md +508 -0
- package/docs/table-of-contents.json +553 -0
- package/docs/table-of-contents.md +289 -0
- package/docs/table.examples.md +1981 -0
- package/docs/table.json +1059 -0
- package/docs/table.md +290 -0
- package/docs/tabs.examples.md +1370 -0
- package/docs/tabs.json +661 -0
- package/docs/tabs.md +211 -0
- package/docs/tag.json +813 -0
- package/docs/tag.md +241 -0
- package/docs/tags-input.json +771 -0
- package/docs/tags-input.md +361 -0
- package/docs/text-field.examples.md +821 -0
- package/docs/text-field.json +604 -0
- package/docs/text-field.md +125 -0
- package/docs/textarea.examples.md +612 -0
- package/docs/textarea.json +440 -0
- package/docs/textarea.md +98 -0
- package/docs/time-field.json +584 -0
- package/docs/time-field.md +291 -0
- package/docs/time-picker.json +679 -0
- package/docs/time-picker.md +315 -0
- package/docs/time-range-picker.examples.md +191 -0
- package/docs/time-range-picker.json +924 -0
- package/docs/time-range-picker.md +152 -0
- package/docs/timeline.json +839 -0
- package/docs/timeline.md +401 -0
- package/docs/toast.json +642 -0
- package/docs/toast.md +311 -0
- package/docs/toggle-group.json +417 -0
- package/docs/toggle-group.md +255 -0
- package/docs/toggle.json +326 -0
- package/docs/toggle.md +222 -0
- package/docs/toolbar.json +380 -0
- package/docs/toolbar.md +240 -0
- package/docs/tooltip.examples.md +664 -0
- package/docs/tooltip.json +604 -0
- package/docs/tooltip.md +146 -0
- package/docs/top-navigation.examples.md +287 -0
- package/docs/top-navigation.json +648 -0
- package/docs/top-navigation.md +138 -0
- package/docs/tour.json +759 -0
- package/docs/tour.md +337 -0
- package/docs/transfer.json +746 -0
- package/docs/transfer.md +273 -0
- package/docs/tree.json +918 -0
- package/docs/tree.md +397 -0
- package/docs/typography.json +317 -0
- package/docs/typography.md +107 -0
- package/docs/upload.examples.md +358 -0
- package/docs/upload.json +1103 -0
- package/docs/upload.md +166 -0
- package/docs/visually-hidden.json +71 -0
- package/docs/visually-hidden.md +42 -0
- package/docs/wizard.json +724 -0
- package/docs/wizard.md +295 -0
- package/fesm2022/slotted-angular-accordion.mjs +247 -0
- package/fesm2022/slotted-angular-accordion.mjs.map +1 -0
- package/fesm2022/slotted-angular-action-bar.mjs +639 -0
- package/fesm2022/slotted-angular-action-bar.mjs.map +1 -0
- package/fesm2022/slotted-angular-action-sheet.mjs +749 -0
- package/fesm2022/slotted-angular-action-sheet.mjs.map +1 -0
- package/fesm2022/slotted-angular-alert.mjs +427 -0
- package/fesm2022/slotted-angular-alert.mjs.map +1 -0
- package/fesm2022/slotted-angular-app-shell.mjs +1334 -0
- package/fesm2022/slotted-angular-app-shell.mjs.map +1 -0
- package/fesm2022/slotted-angular-aspect-ratio.mjs +63 -0
- package/fesm2022/slotted-angular-aspect-ratio.mjs.map +1 -0
- package/fesm2022/slotted-angular-attachment.mjs +595 -0
- package/fesm2022/slotted-angular-attachment.mjs.map +1 -0
- package/fesm2022/slotted-angular-avatar-group.mjs +230 -0
- package/fesm2022/slotted-angular-avatar-group.mjs.map +1 -0
- package/fesm2022/slotted-angular-avatar.mjs +330 -0
- package/fesm2022/slotted-angular-avatar.mjs.map +1 -0
- package/fesm2022/slotted-angular-badge.mjs +255 -0
- package/fesm2022/slotted-angular-badge.mjs.map +1 -0
- package/fesm2022/slotted-angular-breadcrumb.mjs +544 -0
- package/fesm2022/slotted-angular-breadcrumb.mjs.map +1 -0
- package/fesm2022/slotted-angular-button-group.mjs +146 -0
- package/fesm2022/slotted-angular-button-group.mjs.map +1 -0
- package/fesm2022/slotted-angular-button.mjs +692 -0
- package/fesm2022/slotted-angular-button.mjs.map +1 -0
- package/fesm2022/slotted-angular-calendar.mjs +916 -0
- package/fesm2022/slotted-angular-calendar.mjs.map +1 -0
- package/fesm2022/slotted-angular-card.mjs +225 -0
- package/fesm2022/slotted-angular-card.mjs.map +1 -0
- package/fesm2022/slotted-angular-carousel.mjs +840 -0
- package/fesm2022/slotted-angular-carousel.mjs.map +1 -0
- package/fesm2022/slotted-angular-cascader.mjs +1839 -0
- package/fesm2022/slotted-angular-cascader.mjs.map +1 -0
- package/fesm2022/slotted-angular-chart.mjs +974 -0
- package/fesm2022/slotted-angular-chart.mjs.map +1 -0
- package/fesm2022/slotted-angular-checkbox-group.mjs +283 -0
- package/fesm2022/slotted-angular-checkbox-group.mjs.map +1 -0
- package/fesm2022/slotted-angular-checkbox.mjs +468 -0
- package/fesm2022/slotted-angular-checkbox.mjs.map +1 -0
- package/fesm2022/slotted-angular-code-block.mjs +476 -0
- package/fesm2022/slotted-angular-code-block.mjs.map +1 -0
- package/fesm2022/slotted-angular-collapsible.mjs +479 -0
- package/fesm2022/slotted-angular-collapsible.mjs.map +1 -0
- package/fesm2022/slotted-angular-color-picker.mjs +910 -0
- package/fesm2022/slotted-angular-color-picker.mjs.map +1 -0
- package/fesm2022/slotted-angular-column-manager.mjs +1037 -0
- package/fesm2022/slotted-angular-column-manager.mjs.map +1 -0
- package/fesm2022/slotted-angular-combobox.mjs +1480 -0
- package/fesm2022/slotted-angular-combobox.mjs.map +1 -0
- package/fesm2022/slotted-angular-command-palette.mjs +1283 -0
- package/fesm2022/slotted-angular-command-palette.mjs.map +1 -0
- package/fesm2022/slotted-angular-container.mjs +105 -0
- package/fesm2022/slotted-angular-container.mjs.map +1 -0
- package/fesm2022/slotted-angular-context-menu.mjs +221 -0
- package/fesm2022/slotted-angular-context-menu.mjs.map +1 -0
- package/fesm2022/slotted-angular-currency-field.mjs +1131 -0
- package/fesm2022/slotted-angular-currency-field.mjs.map +1 -0
- package/fesm2022/slotted-angular-dashboard-grid.mjs +1928 -0
- package/fesm2022/slotted-angular-dashboard-grid.mjs.map +1 -0
- package/fesm2022/slotted-angular-data-grid.mjs +6697 -0
- package/fesm2022/slotted-angular-data-grid.mjs.map +1 -0
- package/fesm2022/slotted-angular-data-list.mjs +1418 -0
- package/fesm2022/slotted-angular-data-list.mjs.map +1 -0
- package/fesm2022/slotted-angular-date-field.mjs +772 -0
- package/fesm2022/slotted-angular-date-field.mjs.map +1 -0
- package/fesm2022/slotted-angular-date-picker.mjs +690 -0
- package/fesm2022/slotted-angular-date-picker.mjs.map +1 -0
- package/fesm2022/slotted-angular-date-range-picker.mjs +1150 -0
- package/fesm2022/slotted-angular-date-range-picker.mjs.map +1 -0
- package/fesm2022/slotted-angular-datetime-field.mjs +1058 -0
- package/fesm2022/slotted-angular-datetime-field.mjs.map +1 -0
- package/fesm2022/slotted-angular-datetime-picker.mjs +1362 -0
- package/fesm2022/slotted-angular-datetime-picker.mjs.map +1 -0
- package/fesm2022/slotted-angular-datetime-range-picker.mjs +1872 -0
- package/fesm2022/slotted-angular-datetime-range-picker.mjs.map +1 -0
- package/fesm2022/slotted-angular-description-list.mjs +545 -0
- package/fesm2022/slotted-angular-description-list.mjs.map +1 -0
- package/fesm2022/slotted-angular-detail-panel.mjs +754 -0
- package/fesm2022/slotted-angular-detail-panel.mjs.map +1 -0
- package/fesm2022/slotted-angular-dialog.mjs +980 -0
- package/fesm2022/slotted-angular-dialog.mjs.map +1 -0
- package/fesm2022/slotted-angular-divider.mjs +76 -0
- package/fesm2022/slotted-angular-divider.mjs.map +1 -0
- package/fesm2022/slotted-angular-drawer.mjs +1397 -0
- package/fesm2022/slotted-angular-drawer.mjs.map +1 -0
- package/fesm2022/slotted-angular-entity-picker.mjs +1987 -0
- package/fesm2022/slotted-angular-entity-picker.mjs.map +1 -0
- package/fesm2022/slotted-angular-event-calendar.mjs +2934 -0
- package/fesm2022/slotted-angular-event-calendar.mjs.map +1 -0
- package/fesm2022/slotted-angular-field-group.mjs +301 -0
- package/fesm2022/slotted-angular-field-group.mjs.map +1 -0
- package/fesm2022/slotted-angular-field.mjs +928 -0
- package/fesm2022/slotted-angular-field.mjs.map +1 -0
- package/fesm2022/slotted-angular-filter-bar.mjs +3107 -0
- package/fesm2022/slotted-angular-filter-bar.mjs.map +1 -0
- package/fesm2022/slotted-angular-form.mjs +592 -0
- package/fesm2022/slotted-angular-form.mjs.map +1 -0
- package/fesm2022/slotted-angular-fullscreen.mjs +314 -0
- package/fesm2022/slotted-angular-fullscreen.mjs.map +1 -0
- package/fesm2022/slotted-angular-grid.mjs +58 -0
- package/fesm2022/slotted-angular-grid.mjs.map +1 -0
- package/fesm2022/slotted-angular-highlight.mjs +123 -0
- package/fesm2022/slotted-angular-highlight.mjs.map +1 -0
- package/fesm2022/slotted-angular-hover-card.mjs +326 -0
- package/fesm2022/slotted-angular-hover-card.mjs.map +1 -0
- package/fesm2022/slotted-angular-i18n.mjs +75 -0
- package/fesm2022/slotted-angular-i18n.mjs.map +1 -0
- package/fesm2022/slotted-angular-icon.mjs +232 -0
- package/fesm2022/slotted-angular-icon.mjs.map +1 -0
- package/fesm2022/slotted-angular-image.mjs +442 -0
- package/fesm2022/slotted-angular-image.mjs.map +1 -0
- package/fesm2022/slotted-angular-import-export-center.mjs +1792 -0
- package/fesm2022/slotted-angular-import-export-center.mjs.map +1 -0
- package/fesm2022/slotted-angular-inline-message.mjs +280 -0
- package/fesm2022/slotted-angular-inline-message.mjs.map +1 -0
- package/fesm2022/slotted-angular-inline.mjs +52 -0
- package/fesm2022/slotted-angular-inline.mjs.map +1 -0
- package/fesm2022/slotted-angular-kbd.mjs +284 -0
- package/fesm2022/slotted-angular-kbd.mjs.map +1 -0
- package/fesm2022/slotted-angular-link.mjs +182 -0
- package/fesm2022/slotted-angular-link.mjs.map +1 -0
- package/fesm2022/slotted-angular-list-item.mjs +367 -0
- package/fesm2022/slotted-angular-list-item.mjs.map +1 -0
- package/fesm2022/slotted-angular-list.mjs +256 -0
- package/fesm2022/slotted-angular-list.mjs.map +1 -0
- package/fesm2022/slotted-angular-listbox.mjs +1274 -0
- package/fesm2022/slotted-angular-listbox.mjs.map +1 -0
- package/fesm2022/slotted-angular-loading-overlay.mjs +451 -0
- package/fesm2022/slotted-angular-loading-overlay.mjs.map +1 -0
- package/fesm2022/slotted-angular-markdown.mjs +914 -0
- package/fesm2022/slotted-angular-markdown.mjs.map +1 -0
- package/fesm2022/slotted-angular-menu.mjs +1211 -0
- package/fesm2022/slotted-angular-menu.mjs.map +1 -0
- package/fesm2022/slotted-angular-menubar.mjs +230 -0
- package/fesm2022/slotted-angular-menubar.mjs.map +1 -0
- package/fesm2022/slotted-angular-message-scroller.mjs +378 -0
- package/fesm2022/slotted-angular-message-scroller.mjs.map +1 -0
- package/fesm2022/slotted-angular-message.mjs +866 -0
- package/fesm2022/slotted-angular-message.mjs.map +1 -0
- package/fesm2022/slotted-angular-multi-select.mjs +1939 -0
- package/fesm2022/slotted-angular-multi-select.mjs.map +1 -0
- package/fesm2022/slotted-angular-navigation-menu.mjs +770 -0
- package/fesm2022/slotted-angular-navigation-menu.mjs.map +1 -0
- package/fesm2022/slotted-angular-notification-center.mjs +1172 -0
- package/fesm2022/slotted-angular-notification-center.mjs.map +1 -0
- package/fesm2022/slotted-angular-number-field.mjs +966 -0
- package/fesm2022/slotted-angular-number-field.mjs.map +1 -0
- package/fesm2022/slotted-angular-otp-input.mjs +629 -0
- package/fesm2022/slotted-angular-otp-input.mjs.map +1 -0
- package/fesm2022/slotted-angular-page-header.mjs +788 -0
- package/fesm2022/slotted-angular-page-header.mjs.map +1 -0
- package/fesm2022/slotted-angular-page.mjs +255 -0
- package/fesm2022/slotted-angular-page.mjs.map +1 -0
- package/fesm2022/slotted-angular-pagination.mjs +562 -0
- package/fesm2022/slotted-angular-pagination.mjs.map +1 -0
- package/fesm2022/slotted-angular-popover.mjs +799 -0
- package/fesm2022/slotted-angular-popover.mjs.map +1 -0
- package/fesm2022/slotted-angular-progress-indicator.mjs +572 -0
- package/fesm2022/slotted-angular-progress-indicator.mjs.map +1 -0
- package/fesm2022/slotted-angular-prompt-composer.mjs +596 -0
- package/fesm2022/slotted-angular-prompt-composer.mjs.map +1 -0
- package/fesm2022/slotted-angular-prose.mjs +314 -0
- package/fesm2022/slotted-angular-prose.mjs.map +1 -0
- package/fesm2022/slotted-angular-radio-group.mjs +469 -0
- package/fesm2022/slotted-angular-radio-group.mjs.map +1 -0
- package/fesm2022/slotted-angular-rating.mjs +1174 -0
- package/fesm2022/slotted-angular-rating.mjs.map +1 -0
- package/fesm2022/slotted-angular-result-state.mjs +330 -0
- package/fesm2022/slotted-angular-result-state.mjs.map +1 -0
- package/fesm2022/slotted-angular-saved-views.mjs +877 -0
- package/fesm2022/slotted-angular-saved-views.mjs.map +1 -0
- package/fesm2022/slotted-angular-scroll-area.mjs +294 -0
- package/fesm2022/slotted-angular-scroll-area.mjs.map +1 -0
- package/fesm2022/slotted-angular-section.mjs +266 -0
- package/fesm2022/slotted-angular-section.mjs.map +1 -0
- package/fesm2022/slotted-angular-segmented-control.mjs +454 -0
- package/fesm2022/slotted-angular-segmented-control.mjs.map +1 -0
- package/fesm2022/slotted-angular-select.mjs +1899 -0
- package/fesm2022/slotted-angular-select.mjs.map +1 -0
- package/fesm2022/slotted-angular-side-navigation.mjs +1042 -0
- package/fesm2022/slotted-angular-side-navigation.mjs.map +1 -0
- package/fesm2022/slotted-angular-skeleton.mjs +316 -0
- package/fesm2022/slotted-angular-skeleton.mjs.map +1 -0
- package/fesm2022/slotted-angular-slider.mjs +586 -0
- package/fesm2022/slotted-angular-slider.mjs.map +1 -0
- package/fesm2022/slotted-angular-sparkline.mjs +235 -0
- package/fesm2022/slotted-angular-sparkline.mjs.map +1 -0
- package/fesm2022/slotted-angular-split-button.mjs +331 -0
- package/fesm2022/slotted-angular-split-button.mjs.map +1 -0
- package/fesm2022/slotted-angular-splitter.mjs +516 -0
- package/fesm2022/slotted-angular-splitter.mjs.map +1 -0
- package/fesm2022/slotted-angular-stack.mjs +48 -0
- package/fesm2022/slotted-angular-stack.mjs.map +1 -0
- package/fesm2022/slotted-angular-stat-card.mjs +478 -0
- package/fesm2022/slotted-angular-stat-card.mjs.map +1 -0
- package/fesm2022/slotted-angular-status-indicator.mjs +155 -0
- package/fesm2022/slotted-angular-status-indicator.mjs.map +1 -0
- package/fesm2022/slotted-angular-stepper.mjs +536 -0
- package/fesm2022/slotted-angular-stepper.mjs.map +1 -0
- package/fesm2022/slotted-angular-switch.mjs +447 -0
- package/fesm2022/slotted-angular-switch.mjs.map +1 -0
- package/fesm2022/slotted-angular-table-of-contents.mjs +750 -0
- package/fesm2022/slotted-angular-table-of-contents.mjs.map +1 -0
- package/fesm2022/slotted-angular-table.mjs +2518 -0
- package/fesm2022/slotted-angular-table.mjs.map +1 -0
- package/fesm2022/slotted-angular-tabs.mjs +829 -0
- package/fesm2022/slotted-angular-tabs.mjs.map +1 -0
- package/fesm2022/slotted-angular-tag.mjs +595 -0
- package/fesm2022/slotted-angular-tag.mjs.map +1 -0
- package/fesm2022/slotted-angular-tags-input.mjs +1211 -0
- package/fesm2022/slotted-angular-tags-input.mjs.map +1 -0
- package/fesm2022/slotted-angular-text-field.mjs +674 -0
- package/fesm2022/slotted-angular-text-field.mjs.map +1 -0
- package/fesm2022/slotted-angular-textarea.mjs +275 -0
- package/fesm2022/slotted-angular-textarea.mjs.map +1 -0
- package/fesm2022/slotted-angular-theme.mjs +45 -0
- package/fesm2022/slotted-angular-theme.mjs.map +1 -0
- package/fesm2022/slotted-angular-time-field.mjs +895 -0
- package/fesm2022/slotted-angular-time-field.mjs.map +1 -0
- package/fesm2022/slotted-angular-time-picker.mjs +856 -0
- package/fesm2022/slotted-angular-time-picker.mjs.map +1 -0
- package/fesm2022/slotted-angular-time-range-picker.mjs +1534 -0
- package/fesm2022/slotted-angular-time-range-picker.mjs.map +1 -0
- package/fesm2022/slotted-angular-timeline.mjs +928 -0
- package/fesm2022/slotted-angular-timeline.mjs.map +1 -0
- package/fesm2022/slotted-angular-toast.mjs +917 -0
- package/fesm2022/slotted-angular-toast.mjs.map +1 -0
- package/fesm2022/slotted-angular-toggle-group.mjs +311 -0
- package/fesm2022/slotted-angular-toggle-group.mjs.map +1 -0
- package/fesm2022/slotted-angular-toggle.mjs +162 -0
- package/fesm2022/slotted-angular-toggle.mjs.map +1 -0
- package/fesm2022/slotted-angular-toolbar.mjs +536 -0
- package/fesm2022/slotted-angular-toolbar.mjs.map +1 -0
- package/fesm2022/slotted-angular-tooltip.mjs +798 -0
- package/fesm2022/slotted-angular-tooltip.mjs.map +1 -0
- package/fesm2022/slotted-angular-top-navigation.mjs +1308 -0
- package/fesm2022/slotted-angular-top-navigation.mjs.map +1 -0
- package/fesm2022/slotted-angular-tour.mjs +1330 -0
- package/fesm2022/slotted-angular-tour.mjs.map +1 -0
- package/fesm2022/slotted-angular-transfer.mjs +1406 -0
- package/fesm2022/slotted-angular-transfer.mjs.map +1 -0
- package/fesm2022/slotted-angular-tree.mjs +1448 -0
- package/fesm2022/slotted-angular-tree.mjs.map +1 -0
- package/fesm2022/slotted-angular-typography.mjs +184 -0
- package/fesm2022/slotted-angular-typography.mjs.map +1 -0
- package/fesm2022/slotted-angular-upload.mjs +1523 -0
- package/fesm2022/slotted-angular-upload.mjs.map +1 -0
- package/fesm2022/slotted-angular-visually-hidden.mjs +32 -0
- package/fesm2022/slotted-angular-visually-hidden.mjs.map +1 -0
- package/fesm2022/slotted-angular-wizard.mjs +1715 -0
- package/fesm2022/slotted-angular-wizard.mjs.map +1 -0
- package/fesm2022/slotted-angular.mjs +4 -0
- package/fesm2022/slotted-angular.mjs.map +1 -0
- package/package.json +537 -3
- package/types/slotted-angular-accordion.d.ts +156 -0
- package/types/slotted-angular-accordion.d.ts.map +1 -0
- package/types/slotted-angular-action-bar.d.ts +291 -0
- package/types/slotted-angular-action-bar.d.ts.map +1 -0
- package/types/slotted-angular-action-sheet.d.ts +294 -0
- package/types/slotted-angular-action-sheet.d.ts.map +1 -0
- package/types/slotted-angular-alert.d.ts +214 -0
- package/types/slotted-angular-alert.d.ts.map +1 -0
- package/types/slotted-angular-app-shell.d.ts +549 -0
- package/types/slotted-angular-app-shell.d.ts.map +1 -0
- package/types/slotted-angular-aspect-ratio.d.ts +57 -0
- package/types/slotted-angular-aspect-ratio.d.ts.map +1 -0
- package/types/slotted-angular-attachment.d.ts +294 -0
- package/types/slotted-angular-attachment.d.ts.map +1 -0
- package/types/slotted-angular-avatar-group.d.ts +119 -0
- package/types/slotted-angular-avatar-group.d.ts.map +1 -0
- package/types/slotted-angular-avatar.d.ts +202 -0
- package/types/slotted-angular-avatar.d.ts.map +1 -0
- package/types/slotted-angular-badge.d.ts +166 -0
- package/types/slotted-angular-badge.d.ts.map +1 -0
- package/types/slotted-angular-breadcrumb.d.ts +251 -0
- package/types/slotted-angular-breadcrumb.d.ts.map +1 -0
- package/types/slotted-angular-button-group.d.ts +89 -0
- package/types/slotted-angular-button-group.d.ts.map +1 -0
- package/types/slotted-angular-button.d.ts +390 -0
- package/types/slotted-angular-button.d.ts.map +1 -0
- package/types/slotted-angular-calendar.d.ts +280 -0
- package/types/slotted-angular-calendar.d.ts.map +1 -0
- package/types/slotted-angular-card.d.ts +140 -0
- package/types/slotted-angular-card.d.ts.map +1 -0
- package/types/slotted-angular-carousel.d.ts +288 -0
- package/types/slotted-angular-carousel.d.ts.map +1 -0
- package/types/slotted-angular-cascader.d.ts +351 -0
- package/types/slotted-angular-cascader.d.ts.map +1 -0
- package/types/slotted-angular-chart.d.ts +319 -0
- package/types/slotted-angular-chart.d.ts.map +1 -0
- package/types/slotted-angular-checkbox-group.d.ts +156 -0
- package/types/slotted-angular-checkbox-group.d.ts.map +1 -0
- package/types/slotted-angular-checkbox.d.ts +197 -0
- package/types/slotted-angular-checkbox.d.ts.map +1 -0
- package/types/slotted-angular-code-block.d.ts +158 -0
- package/types/slotted-angular-code-block.d.ts.map +1 -0
- package/types/slotted-angular-collapsible.d.ts +272 -0
- package/types/slotted-angular-collapsible.d.ts.map +1 -0
- package/types/slotted-angular-color-picker.d.ts +181 -0
- package/types/slotted-angular-color-picker.d.ts.map +1 -0
- package/types/slotted-angular-column-manager.d.ts +200 -0
- package/types/slotted-angular-column-manager.d.ts.map +1 -0
- package/types/slotted-angular-combobox.d.ts +449 -0
- package/types/slotted-angular-combobox.d.ts.map +1 -0
- package/types/slotted-angular-command-palette.d.ts +256 -0
- package/types/slotted-angular-command-palette.d.ts.map +1 -0
- package/types/slotted-angular-container.d.ts +84 -0
- package/types/slotted-angular-container.d.ts.map +1 -0
- package/types/slotted-angular-context-menu.d.ts +84 -0
- package/types/slotted-angular-context-menu.d.ts.map +1 -0
- package/types/slotted-angular-currency-field.d.ts +480 -0
- package/types/slotted-angular-currency-field.d.ts.map +1 -0
- package/types/slotted-angular-dashboard-grid.d.ts +341 -0
- package/types/slotted-angular-dashboard-grid.d.ts.map +1 -0
- package/types/slotted-angular-data-grid.d.ts +1077 -0
- package/types/slotted-angular-data-grid.d.ts.map +1 -0
- package/types/slotted-angular-data-list.d.ts +272 -0
- package/types/slotted-angular-data-list.d.ts.map +1 -0
- package/types/slotted-angular-date-field.d.ts +320 -0
- package/types/slotted-angular-date-field.d.ts.map +1 -0
- package/types/slotted-angular-date-picker.d.ts +224 -0
- package/types/slotted-angular-date-picker.d.ts.map +1 -0
- package/types/slotted-angular-date-range-picker.d.ts +310 -0
- package/types/slotted-angular-date-range-picker.d.ts.map +1 -0
- package/types/slotted-angular-datetime-field.d.ts +362 -0
- package/types/slotted-angular-datetime-field.d.ts.map +1 -0
- package/types/slotted-angular-datetime-picker.d.ts +370 -0
- package/types/slotted-angular-datetime-picker.d.ts.map +1 -0
- package/types/slotted-angular-datetime-range-picker.d.ts +459 -0
- package/types/slotted-angular-datetime-range-picker.d.ts.map +1 -0
- package/types/slotted-angular-description-list.d.ts +281 -0
- package/types/slotted-angular-description-list.d.ts.map +1 -0
- package/types/slotted-angular-detail-panel.d.ts +240 -0
- package/types/slotted-angular-detail-panel.d.ts.map +1 -0
- package/types/slotted-angular-dialog.d.ts +497 -0
- package/types/slotted-angular-dialog.d.ts.map +1 -0
- package/types/slotted-angular-divider.d.ts +40 -0
- package/types/slotted-angular-divider.d.ts.map +1 -0
- package/types/slotted-angular-drawer.d.ts +532 -0
- package/types/slotted-angular-drawer.d.ts.map +1 -0
- package/types/slotted-angular-entity-picker.d.ts +338 -0
- package/types/slotted-angular-entity-picker.d.ts.map +1 -0
- package/types/slotted-angular-event-calendar.d.ts +574 -0
- package/types/slotted-angular-event-calendar.d.ts.map +1 -0
- package/types/slotted-angular-field-group.d.ts +152 -0
- package/types/slotted-angular-field-group.d.ts.map +1 -0
- package/types/slotted-angular-field.d.ts +535 -0
- package/types/slotted-angular-field.d.ts.map +1 -0
- package/types/slotted-angular-filter-bar.d.ts +573 -0
- package/types/slotted-angular-filter-bar.d.ts.map +1 -0
- package/types/slotted-angular-form.d.ts +298 -0
- package/types/slotted-angular-form.d.ts.map +1 -0
- package/types/slotted-angular-fullscreen.d.ts +145 -0
- package/types/slotted-angular-fullscreen.d.ts.map +1 -0
- package/types/slotted-angular-grid.d.ts +50 -0
- package/types/slotted-angular-grid.d.ts.map +1 -0
- package/types/slotted-angular-highlight.d.ts +93 -0
- package/types/slotted-angular-highlight.d.ts.map +1 -0
- package/types/slotted-angular-hover-card.d.ts +140 -0
- package/types/slotted-angular-hover-card.d.ts.map +1 -0
- package/types/slotted-angular-i18n.d.ts +46 -0
- package/types/slotted-angular-i18n.d.ts.map +1 -0
- package/types/slotted-angular-icon.d.ts +94 -0
- package/types/slotted-angular-icon.d.ts.map +1 -0
- package/types/slotted-angular-image.d.ts +251 -0
- package/types/slotted-angular-image.d.ts.map +1 -0
- package/types/slotted-angular-import-export-center.d.ts +351 -0
- package/types/slotted-angular-import-export-center.d.ts.map +1 -0
- package/types/slotted-angular-inline-message.d.ts +195 -0
- package/types/slotted-angular-inline-message.d.ts.map +1 -0
- package/types/slotted-angular-inline.d.ts +41 -0
- package/types/slotted-angular-inline.d.ts.map +1 -0
- package/types/slotted-angular-kbd.d.ts +174 -0
- package/types/slotted-angular-kbd.d.ts.map +1 -0
- package/types/slotted-angular-link.d.ts +94 -0
- package/types/slotted-angular-link.d.ts.map +1 -0
- package/types/slotted-angular-list-item.d.ts +210 -0
- package/types/slotted-angular-list-item.d.ts.map +1 -0
- package/types/slotted-angular-list.d.ts +176 -0
- package/types/slotted-angular-list.d.ts.map +1 -0
- package/types/slotted-angular-listbox.d.ts +470 -0
- package/types/slotted-angular-listbox.d.ts.map +1 -0
- package/types/slotted-angular-loading-overlay.d.ts +219 -0
- package/types/slotted-angular-loading-overlay.d.ts.map +1 -0
- package/types/slotted-angular-markdown.d.ts +172 -0
- package/types/slotted-angular-markdown.d.ts.map +1 -0
- package/types/slotted-angular-menu.d.ts +448 -0
- package/types/slotted-angular-menu.d.ts.map +1 -0
- package/types/slotted-angular-menubar.d.ts +90 -0
- package/types/slotted-angular-menubar.d.ts.map +1 -0
- package/types/slotted-angular-message-scroller.d.ts +151 -0
- package/types/slotted-angular-message-scroller.d.ts.map +1 -0
- package/types/slotted-angular-message.d.ts +348 -0
- package/types/slotted-angular-message.d.ts.map +1 -0
- package/types/slotted-angular-multi-select.d.ts +462 -0
- package/types/slotted-angular-multi-select.d.ts.map +1 -0
- package/types/slotted-angular-navigation-menu.d.ts +309 -0
- package/types/slotted-angular-navigation-menu.d.ts.map +1 -0
- package/types/slotted-angular-notification-center.d.ts +318 -0
- package/types/slotted-angular-notification-center.d.ts.map +1 -0
- package/types/slotted-angular-number-field.d.ts +402 -0
- package/types/slotted-angular-number-field.d.ts.map +1 -0
- package/types/slotted-angular-otp-input.d.ts +286 -0
- package/types/slotted-angular-otp-input.d.ts.map +1 -0
- package/types/slotted-angular-page-header.d.ts +334 -0
- package/types/slotted-angular-page-header.d.ts.map +1 -0
- package/types/slotted-angular-page.d.ts +141 -0
- package/types/slotted-angular-page.d.ts.map +1 -0
- package/types/slotted-angular-pagination.d.ts +213 -0
- package/types/slotted-angular-pagination.d.ts.map +1 -0
- package/types/slotted-angular-popover.d.ts +366 -0
- package/types/slotted-angular-popover.d.ts.map +1 -0
- package/types/slotted-angular-progress-indicator.d.ts +312 -0
- package/types/slotted-angular-progress-indicator.d.ts.map +1 -0
- package/types/slotted-angular-prompt-composer.d.ts +242 -0
- package/types/slotted-angular-prompt-composer.d.ts.map +1 -0
- package/types/slotted-angular-prose.d.ts +171 -0
- package/types/slotted-angular-prose.d.ts.map +1 -0
- package/types/slotted-angular-radio-group.d.ts +268 -0
- package/types/slotted-angular-radio-group.d.ts.map +1 -0
- package/types/slotted-angular-rating.d.ts +374 -0
- package/types/slotted-angular-rating.d.ts.map +1 -0
- package/types/slotted-angular-result-state.d.ts +217 -0
- package/types/slotted-angular-result-state.d.ts.map +1 -0
- package/types/slotted-angular-saved-views.d.ts +198 -0
- package/types/slotted-angular-saved-views.d.ts.map +1 -0
- package/types/slotted-angular-scroll-area.d.ts +186 -0
- package/types/slotted-angular-scroll-area.d.ts.map +1 -0
- package/types/slotted-angular-section.d.ts +143 -0
- package/types/slotted-angular-section.d.ts.map +1 -0
- package/types/slotted-angular-segmented-control.d.ts +251 -0
- package/types/slotted-angular-segmented-control.d.ts.map +1 -0
- package/types/slotted-angular-select.d.ts +507 -0
- package/types/slotted-angular-select.d.ts.map +1 -0
- package/types/slotted-angular-side-navigation.d.ts +373 -0
- package/types/slotted-angular-side-navigation.d.ts.map +1 -0
- package/types/slotted-angular-skeleton.d.ts +198 -0
- package/types/slotted-angular-skeleton.d.ts.map +1 -0
- package/types/slotted-angular-slider.d.ts +216 -0
- package/types/slotted-angular-slider.d.ts.map +1 -0
- package/types/slotted-angular-sparkline.d.ts +106 -0
- package/types/slotted-angular-sparkline.d.ts.map +1 -0
- package/types/slotted-angular-split-button.d.ts +180 -0
- package/types/slotted-angular-split-button.d.ts.map +1 -0
- package/types/slotted-angular-splitter.d.ts +206 -0
- package/types/slotted-angular-splitter.d.ts.map +1 -0
- package/types/slotted-angular-stack.d.ts +38 -0
- package/types/slotted-angular-stack.d.ts.map +1 -0
- package/types/slotted-angular-stat-card.d.ts +232 -0
- package/types/slotted-angular-stat-card.d.ts.map +1 -0
- package/types/slotted-angular-status-indicator.d.ts +106 -0
- package/types/slotted-angular-status-indicator.d.ts.map +1 -0
- package/types/slotted-angular-stepper.d.ts +198 -0
- package/types/slotted-angular-stepper.d.ts.map +1 -0
- package/types/slotted-angular-switch.d.ts +243 -0
- package/types/slotted-angular-switch.d.ts.map +1 -0
- package/types/slotted-angular-table-of-contents.d.ts +210 -0
- package/types/slotted-angular-table-of-contents.d.ts.map +1 -0
- package/types/slotted-angular-table.d.ts +888 -0
- package/types/slotted-angular-table.d.ts.map +1 -0
- package/types/slotted-angular-tabs.d.ts +340 -0
- package/types/slotted-angular-tabs.d.ts.map +1 -0
- package/types/slotted-angular-tag.d.ts +279 -0
- package/types/slotted-angular-tag.d.ts.map +1 -0
- package/types/slotted-angular-tags-input.d.ts +302 -0
- package/types/slotted-angular-tags-input.d.ts.map +1 -0
- package/types/slotted-angular-text-field.d.ts +334 -0
- package/types/slotted-angular-text-field.d.ts.map +1 -0
- package/types/slotted-angular-textarea.d.ts +150 -0
- package/types/slotted-angular-textarea.d.ts.map +1 -0
- package/types/slotted-angular-theme.d.ts +26 -0
- package/types/slotted-angular-theme.d.ts.map +1 -0
- package/types/slotted-angular-time-field.d.ts +300 -0
- package/types/slotted-angular-time-field.d.ts.map +1 -0
- package/types/slotted-angular-time-picker.d.ts +260 -0
- package/types/slotted-angular-time-picker.d.ts.map +1 -0
- package/types/slotted-angular-time-range-picker.d.ts +401 -0
- package/types/slotted-angular-time-range-picker.d.ts.map +1 -0
- package/types/slotted-angular-timeline.d.ts +329 -0
- package/types/slotted-angular-timeline.d.ts.map +1 -0
- package/types/slotted-angular-toast.d.ts +340 -0
- package/types/slotted-angular-toast.d.ts.map +1 -0
- package/types/slotted-angular-toggle-group.d.ts +167 -0
- package/types/slotted-angular-toggle-group.d.ts.map +1 -0
- package/types/slotted-angular-toggle.d.ts +106 -0
- package/types/slotted-angular-toggle.d.ts.map +1 -0
- package/types/slotted-angular-toolbar.d.ts +252 -0
- package/types/slotted-angular-toolbar.d.ts.map +1 -0
- package/types/slotted-angular-tooltip.d.ts +388 -0
- package/types/slotted-angular-tooltip.d.ts.map +1 -0
- package/types/slotted-angular-top-navigation.d.ts +442 -0
- package/types/slotted-angular-top-navigation.d.ts.map +1 -0
- package/types/slotted-angular-tour.d.ts +440 -0
- package/types/slotted-angular-tour.d.ts.map +1 -0
- package/types/slotted-angular-transfer.d.ts +296 -0
- package/types/slotted-angular-transfer.d.ts.map +1 -0
- package/types/slotted-angular-tree.d.ts +499 -0
- package/types/slotted-angular-tree.d.ts.map +1 -0
- package/types/slotted-angular-typography.d.ts +89 -0
- package/types/slotted-angular-typography.d.ts.map +1 -0
- package/types/slotted-angular-upload.d.ts +365 -0
- package/types/slotted-angular-upload.d.ts.map +1 -0
- package/types/slotted-angular-visually-hidden.d.ts +19 -0
- package/types/slotted-angular-visually-hidden.d.ts.map +1 -0
- package/types/slotted-angular-wizard.d.ts +441 -0
- package/types/slotted-angular-wizard.d.ts.map +1 -0
- package/types/slotted-angular.d.ts +3 -0
- package/types/slotted-angular.d.ts.map +1 -0
|
@@ -0,0 +1,1981 @@
|
|
|
1
|
+
<!-- index: ./index.md -->
|
|
2
|
+
# table
|
|
3
|
+
|
|
4
|
+
`data-ui="table"` · Semantic table with sorting, filters and selection.
|
|
5
|
+
|
|
6
|
+
## Examples
|
|
7
|
+
|
|
8
|
+
### Playground
|
|
9
|
+
|
|
10
|
+
Every axis on one table, driven by the controls below the canvas. Change the variant, turn the stripes on, then narrow the window: the table scrolls inside its own frame rather than pushing the page over.
|
|
11
|
+
|
|
12
|
+
Excerpt — not a complete module
|
|
13
|
+
|
|
14
|
+
```html
|
|
15
|
+
<div slTable [columns]="3">
|
|
16
|
+
<div slTableContent>
|
|
17
|
+
<caption slTableCaption>
|
|
18
|
+
Invoices
|
|
19
|
+
</caption>
|
|
20
|
+
<thead slTableHead>
|
|
21
|
+
<tr slTableRow>
|
|
22
|
+
<th slTableColumnHeader>Invoice</th>
|
|
23
|
+
<th slTableColumnHeader>Client</th>
|
|
24
|
+
<th slTableColumnHeader numeric>Amount</th>
|
|
25
|
+
</tr>
|
|
26
|
+
</thead>
|
|
27
|
+
<tbody slTableBody>
|
|
28
|
+
@for (invoice of invoices(); track invoice.id) {
|
|
29
|
+
<tr slTableRow [value]="invoice.id">
|
|
30
|
+
<th slTableRowHeader>{{ invoice.id }}</th>
|
|
31
|
+
<td slTableCell>{{ invoice.client }}</td>
|
|
32
|
+
<td slTableCell numeric>{{ invoice.amount }}</td>
|
|
33
|
+
</tr>
|
|
34
|
+
}
|
|
35
|
+
</tbody>
|
|
36
|
+
</div>
|
|
37
|
+
</div>
|
|
38
|
+
```
|
|
39
|
+
|
|
40
|
+
### Nothing, a rule, or a frame
|
|
41
|
+
|
|
42
|
+
Plain is the form that belongs inside a card, where the card already draws the box. Ruled puts a hairline between records. Framed is the listing screen: the set reads as one object, and the footer bar sits inside it.
|
|
43
|
+
|
|
44
|
+
Excerpt — not a complete module
|
|
45
|
+
|
|
46
|
+
```html
|
|
47
|
+
<div slTable variant="plain"></div>
|
|
48
|
+
<div slTable variant="ruled"></div>
|
|
49
|
+
<div slTable variant="framed"></div>
|
|
50
|
+
```
|
|
51
|
+
|
|
52
|
+
### A stripe to carry the eye across
|
|
53
|
+
|
|
54
|
+
Off by default, because a stripe costs a row its own state colours. It is mixed from the ink at five per cent, one step under the header band, and every state is painted over it: a striped row that is selected reads as selected.
|
|
55
|
+
|
|
56
|
+
Example
|
|
57
|
+
|
|
58
|
+
```ts
|
|
59
|
+
import { Component } from '@angular/core';
|
|
60
|
+
import {
|
|
61
|
+
SlTable,
|
|
62
|
+
SlTableBody,
|
|
63
|
+
SlTableCell,
|
|
64
|
+
SlTableColumnHeader,
|
|
65
|
+
SlTableContent,
|
|
66
|
+
SlTableHead,
|
|
67
|
+
SlTableRow,
|
|
68
|
+
SlTableRowHeader,
|
|
69
|
+
} from '@slotted/angular/table';
|
|
70
|
+
|
|
71
|
+
const STOCK = [
|
|
72
|
+
{ sku: 'PRD-0412', product: 'Chai', warehouse: 'Reno', onHand: 390, reserved: 42 },
|
|
73
|
+
{ sku: 'PRD-0413', product: 'Chang', warehouse: 'Reno', onHand: 170, reserved: 12 },
|
|
74
|
+
{ sku: 'PRD-0414', product: 'Aniseed Syrup', warehouse: 'Columbus', onHand: 130, reserved: 70 },
|
|
75
|
+
{
|
|
76
|
+
sku: 'PRD-0415',
|
|
77
|
+
product: "Chef Anton's Cajun Seasoning",
|
|
78
|
+
warehouse: 'Savannah',
|
|
79
|
+
onHand: 530,
|
|
80
|
+
reserved: 0,
|
|
81
|
+
},
|
|
82
|
+
{
|
|
83
|
+
sku: 'PRD-0416',
|
|
84
|
+
product: "Grandma's Boysenberry Spread",
|
|
85
|
+
warehouse: 'Columbus',
|
|
86
|
+
onHand: 120,
|
|
87
|
+
reserved: 25,
|
|
88
|
+
},
|
|
89
|
+
{
|
|
90
|
+
sku: 'PRD-0417',
|
|
91
|
+
product: 'Northwoods Cranberry Sauce',
|
|
92
|
+
warehouse: 'Reno',
|
|
93
|
+
onHand: 60,
|
|
94
|
+
reserved: 60,
|
|
95
|
+
},
|
|
96
|
+
];
|
|
97
|
+
|
|
98
|
+
@Component({
|
|
99
|
+
selector: 'app-table-striped',
|
|
100
|
+
imports: [
|
|
101
|
+
SlTable,
|
|
102
|
+
SlTableBody,
|
|
103
|
+
SlTableCell,
|
|
104
|
+
SlTableColumnHeader,
|
|
105
|
+
SlTableContent,
|
|
106
|
+
SlTableHead,
|
|
107
|
+
SlTableRow,
|
|
108
|
+
SlTableRowHeader,
|
|
109
|
+
],
|
|
110
|
+
template: `
|
|
111
|
+
<div slTable [columns]="5" striped>
|
|
112
|
+
<div slTableContent aria-label="Stock on hand">
|
|
113
|
+
<thead slTableHead>
|
|
114
|
+
<tr slTableRow>
|
|
115
|
+
<th slTableColumnHeader>SKU</th>
|
|
116
|
+
<th slTableColumnHeader>Product</th>
|
|
117
|
+
<th slTableColumnHeader>Warehouse</th>
|
|
118
|
+
<th slTableColumnHeader numeric>On hand</th>
|
|
119
|
+
<th slTableColumnHeader numeric>Reserved</th>
|
|
120
|
+
</tr>
|
|
121
|
+
</thead>
|
|
122
|
+
<tbody slTableBody>
|
|
123
|
+
@for (item of stock; track item.sku) {
|
|
124
|
+
<tr slTableRow [value]="item.sku">
|
|
125
|
+
<th slTableRowHeader text="nowrap">{{ item.sku }}</th>
|
|
126
|
+
<td slTableCell>{{ item.product }}</td>
|
|
127
|
+
<td slTableCell>{{ item.warehouse }}</td>
|
|
128
|
+
<td slTableCell numeric>{{ item.onHand }}</td>
|
|
129
|
+
<td slTableCell numeric>{{ item.reserved }}</td>
|
|
130
|
+
</tr>
|
|
131
|
+
}
|
|
132
|
+
</tbody>
|
|
133
|
+
</div>
|
|
134
|
+
</div>
|
|
135
|
+
`,
|
|
136
|
+
})
|
|
137
|
+
export class TableStriped {
|
|
138
|
+
readonly stock = STOCK;
|
|
139
|
+
}
|
|
140
|
+
```
|
|
141
|
+
|
|
142
|
+
### Ordered by one column, and said out loud
|
|
143
|
+
|
|
144
|
+
Press a header: ascending, then descending, then none. The family holds the descriptor and reorders nothing — the rows are yours — so apply it to your own array or send it to your query. The change is announced, because aria-sort alone is silent.
|
|
145
|
+
|
|
146
|
+
Example
|
|
147
|
+
|
|
148
|
+
```ts
|
|
149
|
+
import { Component, computed, signal } from '@angular/core';
|
|
150
|
+
import {
|
|
151
|
+
SlTable,
|
|
152
|
+
SlTableBody,
|
|
153
|
+
SlTableCell,
|
|
154
|
+
SlTableColumnHeader,
|
|
155
|
+
SlTableContent,
|
|
156
|
+
SlTableHead,
|
|
157
|
+
SlTableRow,
|
|
158
|
+
SlTableRowHeader,
|
|
159
|
+
SlTableSort,
|
|
160
|
+
type TableSortDescriptor,
|
|
161
|
+
} from '@slotted/angular/table';
|
|
162
|
+
|
|
163
|
+
const USD = new Intl.NumberFormat('en-US', { currency: 'USD', style: 'currency' });
|
|
164
|
+
|
|
165
|
+
const ORDERS = [
|
|
166
|
+
{ id: 'SO-10421', customer: 'Alfreds Futterkiste', placed: '2026-09-28', total: 1240 },
|
|
167
|
+
{ id: 'SO-10422', customer: "Bon app'", placed: '2026-09-29', total: 860.5 },
|
|
168
|
+
{ id: 'SO-10423', customer: 'Ernst Handel', placed: '2026-09-27', total: 3410.25 },
|
|
169
|
+
{ id: 'SO-10424', customer: 'Folk och fä HB', placed: '2026-09-30', total: 512 },
|
|
170
|
+
];
|
|
171
|
+
|
|
172
|
+
type Order = (typeof ORDERS)[number];
|
|
173
|
+
|
|
174
|
+
function sortOrders(rows: readonly Order[], sort: TableSortDescriptor | null): readonly Order[] {
|
|
175
|
+
if (sort === null) return rows;
|
|
176
|
+
const key = sort.column as keyof Order;
|
|
177
|
+
const sign = sort.direction === 'ascending' ? 1 : -1;
|
|
178
|
+
return [...rows].sort((a, b) =>
|
|
179
|
+
typeof a[key] === 'number'
|
|
180
|
+
? ((a[key] as number) - (b[key] as number)) * sign
|
|
181
|
+
: String(a[key]).localeCompare(String(b[key])) * sign,
|
|
182
|
+
);
|
|
183
|
+
}
|
|
184
|
+
|
|
185
|
+
@Component({
|
|
186
|
+
selector: 'app-table-sorting',
|
|
187
|
+
imports: [
|
|
188
|
+
SlTable,
|
|
189
|
+
SlTableBody,
|
|
190
|
+
SlTableCell,
|
|
191
|
+
SlTableColumnHeader,
|
|
192
|
+
SlTableContent,
|
|
193
|
+
SlTableHead,
|
|
194
|
+
SlTableRow,
|
|
195
|
+
SlTableRowHeader,
|
|
196
|
+
SlTableSort,
|
|
197
|
+
],
|
|
198
|
+
template: `
|
|
199
|
+
<div slTable [columns]="4" [(sort)]="sort">
|
|
200
|
+
<div slTableContent aria-label="Recent orders">
|
|
201
|
+
<thead slTableHead>
|
|
202
|
+
<tr slTableRow>
|
|
203
|
+
<th slTableColumnHeader column="id"><button slTableSort>Order</button></th>
|
|
204
|
+
<th slTableColumnHeader column="customer"><button slTableSort>Customer</button></th>
|
|
205
|
+
<th slTableColumnHeader column="placed"><button slTableSort>Placed</button></th>
|
|
206
|
+
<th slTableColumnHeader column="total" numeric><button slTableSort>Total</button></th>
|
|
207
|
+
</tr>
|
|
208
|
+
</thead>
|
|
209
|
+
<tbody slTableBody>
|
|
210
|
+
@for (order of rows(); track order.id) {
|
|
211
|
+
<tr slTableRow [value]="order.id">
|
|
212
|
+
<th slTableRowHeader text="nowrap">{{ order.id }}</th>
|
|
213
|
+
<td slTableCell>{{ order.customer }}</td>
|
|
214
|
+
<td slTableCell text="nowrap">{{ order.placed }}</td>
|
|
215
|
+
<td slTableCell numeric>{{ usd.format(order.total) }}</td>
|
|
216
|
+
</tr>
|
|
217
|
+
}
|
|
218
|
+
</tbody>
|
|
219
|
+
</div>
|
|
220
|
+
</div>
|
|
221
|
+
`,
|
|
222
|
+
})
|
|
223
|
+
export class TableSorting {
|
|
224
|
+
readonly sort = signal<TableSortDescriptor | null>({ column: 'placed', direction: 'descending' });
|
|
225
|
+
readonly rows = computed(() => sortOrders(ORDERS, this.sort()));
|
|
226
|
+
readonly usd = USD;
|
|
227
|
+
}
|
|
228
|
+
```
|
|
229
|
+
|
|
230
|
+
### A filter, beside the name it filters
|
|
231
|
+
|
|
232
|
+
The family draws the filter: a trigger on the column boundary and a panel that searches, covers what the search left, counts what you counted, and edits a draft. Nothing reaches you until Apply — Escape and a press outside put back the set the panel opened with. What the set means is still your query.
|
|
233
|
+
|
|
234
|
+
Excerpt — not a complete module
|
|
235
|
+
|
|
236
|
+
```html
|
|
237
|
+
<th slTableColumnHeader column="client">
|
|
238
|
+
<button slTableSort>Client</button>
|
|
239
|
+
<span slTableColumnActions>
|
|
240
|
+
<span slTableTextFilter columnLabel="client" [(value)]="client"></span>
|
|
241
|
+
</span>
|
|
242
|
+
</th>
|
|
243
|
+
```
|
|
244
|
+
|
|
245
|
+
### A column filtered to the values you named
|
|
246
|
+
|
|
247
|
+
The set filter: a list, a search past eight values through the same locale collator Combobox uses, and a checkbox that covers exactly what the search left. Counts are yours to supply. Nothing reaches you until Apply — Escape and a press outside put back the descriptor the panel opened with — and a filtered column says what is applied in the trigger own name.
|
|
248
|
+
|
|
249
|
+
Example
|
|
250
|
+
|
|
251
|
+
```ts
|
|
252
|
+
import { Component, computed, signal } from '@angular/core';
|
|
253
|
+
import { createFilterPredicate, type SetFilter } from '@slotted/core/filter';
|
|
254
|
+
import {
|
|
255
|
+
SlTable,
|
|
256
|
+
SlTableBody,
|
|
257
|
+
SlTableCell,
|
|
258
|
+
SlTableColumnActions,
|
|
259
|
+
SlTableColumnHeader,
|
|
260
|
+
SlTableContent,
|
|
261
|
+
SlTableHead,
|
|
262
|
+
SlTableRow,
|
|
263
|
+
SlTableRowHeader,
|
|
264
|
+
SlTableSetFilter,
|
|
265
|
+
} from '@slotted/angular/table';
|
|
266
|
+
|
|
267
|
+
const ORDERS = [
|
|
268
|
+
{ id: 'SO-10421', customer: 'Alfreds Futterkiste', warehouse: 'Reno', status: 'Shipped' },
|
|
269
|
+
{ id: 'SO-10422', customer: "Bon app'", warehouse: 'Columbus', status: 'Processing' },
|
|
270
|
+
{ id: 'SO-10423', customer: 'Ernst Handel', warehouse: 'Savannah', status: 'On hold' },
|
|
271
|
+
{ id: 'SO-10424', customer: 'Folk och fä HB', warehouse: 'Reno', status: 'Delivered' },
|
|
272
|
+
{ id: 'SO-10425', customer: 'QUICK-Stop', warehouse: 'Columbus', status: 'Shipped' },
|
|
273
|
+
{ id: 'SO-10426', customer: 'Hanari Carnes', warehouse: 'Savannah', status: 'Processing' },
|
|
274
|
+
];
|
|
275
|
+
|
|
276
|
+
const STATUSES = ['Processing', 'On hold', 'Shipped', 'Delivered'].map((value) => ({
|
|
277
|
+
value,
|
|
278
|
+
count: ORDERS.filter((order) => order.status === value).length,
|
|
279
|
+
}));
|
|
280
|
+
|
|
281
|
+
@Component({
|
|
282
|
+
selector: 'app-table-filter',
|
|
283
|
+
imports: [
|
|
284
|
+
SlTable,
|
|
285
|
+
SlTableBody,
|
|
286
|
+
SlTableCell,
|
|
287
|
+
SlTableColumnActions,
|
|
288
|
+
SlTableColumnHeader,
|
|
289
|
+
SlTableContent,
|
|
290
|
+
SlTableHead,
|
|
291
|
+
SlTableRow,
|
|
292
|
+
SlTableRowHeader,
|
|
293
|
+
SlTableSetFilter,
|
|
294
|
+
],
|
|
295
|
+
template: `
|
|
296
|
+
<div slTable [columns]="4">
|
|
297
|
+
<div slTableContent aria-label="Open orders">
|
|
298
|
+
<thead slTableHead>
|
|
299
|
+
<tr slTableRow>
|
|
300
|
+
<th slTableColumnHeader>Order</th>
|
|
301
|
+
<th slTableColumnHeader>Customer</th>
|
|
302
|
+
<th slTableColumnHeader>Warehouse</th>
|
|
303
|
+
<th slTableColumnHeader>
|
|
304
|
+
Status
|
|
305
|
+
<span slTableColumnActions>
|
|
306
|
+
<span
|
|
307
|
+
slTableSetFilter
|
|
308
|
+
columnLabel="status"
|
|
309
|
+
[options]="statuses"
|
|
310
|
+
[(value)]="status"
|
|
311
|
+
></span>
|
|
312
|
+
</span>
|
|
313
|
+
</th>
|
|
314
|
+
</tr>
|
|
315
|
+
</thead>
|
|
316
|
+
<tbody slTableBody>
|
|
317
|
+
@for (order of rows(); track order.id) {
|
|
318
|
+
<tr slTableRow [value]="order.id">
|
|
319
|
+
<th slTableRowHeader text="nowrap">{{ order.id }}</th>
|
|
320
|
+
<td slTableCell>{{ order.customer }}</td>
|
|
321
|
+
<td slTableCell>{{ order.warehouse }}</td>
|
|
322
|
+
<td slTableCell>{{ order.status }}</td>
|
|
323
|
+
</tr>
|
|
324
|
+
}
|
|
325
|
+
</tbody>
|
|
326
|
+
</div>
|
|
327
|
+
</div>
|
|
328
|
+
`,
|
|
329
|
+
})
|
|
330
|
+
export class TableFilter {
|
|
331
|
+
readonly statuses = STATUSES;
|
|
332
|
+
readonly status = signal<SetFilter | null>(null);
|
|
333
|
+
readonly rows = computed(() => {
|
|
334
|
+
const keep = createFilterPredicate(this.status());
|
|
335
|
+
return ORDERS.filter((order) => keep(order.status));
|
|
336
|
+
});
|
|
337
|
+
}
|
|
338
|
+
```
|
|
339
|
+
|
|
340
|
+
### Four columns, four kinds, one predicate
|
|
341
|
+
|
|
342
|
+
Text, number, date and boolean, each with the operators its type has and each typed as itself — a slTableTextFilter value is a TextFilter model, and you never unwrap a union to read it. createRowPredicate joins the four, so the screen filters without a switch of its own.
|
|
343
|
+
|
|
344
|
+
Excerpt — not a complete module
|
|
345
|
+
|
|
346
|
+
```html
|
|
347
|
+
<span slTableTextFilter columnLabel="client" [(value)]="client"></span>
|
|
348
|
+
<span slTableNumberFilter columnLabel="amount" [(value)]="total"></span>
|
|
349
|
+
<span slTableDateFilter columnLabel="due" [(value)]="dueAt"></span>
|
|
350
|
+
<span slTableBooleanFilter columnLabel="overdue" [(value)]="overdue"></span>
|
|
351
|
+
```
|
|
352
|
+
|
|
353
|
+
### Two conditions, and the shapes an operator makes
|
|
354
|
+
|
|
355
|
+
Between takes two operands and is empty takes none, so the panel grows a field or loses both — and says so, because a form that changes shape under a reader who cannot see it says nothing otherwise. The second condition appears once the first is complete, joined by And or Or; past two, a rule set is Filter Bar work.
|
|
356
|
+
|
|
357
|
+
Excerpt — not a complete module
|
|
358
|
+
|
|
359
|
+
```html
|
|
360
|
+
<span slTableNumberFilter columnLabel="amount" [(value)]="amount"></span>
|
|
361
|
+
<span slTableTextFilter columnLabel="client" [conditions]="1" [(value)]="client"></span>
|
|
362
|
+
```
|
|
363
|
+
|
|
364
|
+
### A time column, and a window that crosses midnight
|
|
365
|
+
|
|
366
|
+
slTableTimeFilter draws the time picker, and one time range picker for between, and holds ISO text at the column granularity — 22:00 at a minute, 22:00:00 at a second — which is the precision the engine compares at. A between whose start is later than its end is the overnight window, not an empty set: 22:00 to 02:00 keeps 23:30 and 01:15. The range picker marks that pair out of order until its wrap capability lands; the filter applies it as the window either way. Your shifts go in through presets.
|
|
367
|
+
|
|
368
|
+
Excerpt — not a complete module
|
|
369
|
+
|
|
370
|
+
```html
|
|
371
|
+
<ng-template #shifts>
|
|
372
|
+
<button slTimeRangePickerPreset [range]="morning">Morning</button>
|
|
373
|
+
</ng-template>
|
|
374
|
+
<span
|
|
375
|
+
slTableTimeFilter
|
|
376
|
+
columnLabel="cut-off"
|
|
377
|
+
granularity="minute"
|
|
378
|
+
[presets]="shifts"
|
|
379
|
+
[(value)]="cutoff"
|
|
380
|
+
></span>
|
|
381
|
+
```
|
|
382
|
+
|
|
383
|
+
### A date-time column, at the precision you wrote
|
|
384
|
+
|
|
385
|
+
slTableDateTimeFilter draws the date-time picker, and one date-time range picker for between, and holds 2026-09-14T09:00 as text. Compared at the operand own precision, so after 2026-09-14T09 starts at ten o clock and is 2026-09-14 matches the whole day. A condition with one half missing is inactive until both halves exist, and Apply reports nothing for it. Your windows go in through presets.
|
|
386
|
+
|
|
387
|
+
Excerpt — not a complete module
|
|
388
|
+
|
|
389
|
+
```html
|
|
390
|
+
<ng-template #windows>
|
|
391
|
+
<button slDateTimeRangePickerPreset [range]="earlyOctober">Early October</button>
|
|
392
|
+
</ng-template>
|
|
393
|
+
<span
|
|
394
|
+
slTableDateTimeFilter
|
|
395
|
+
columnLabel="scheduled"
|
|
396
|
+
timeZone="Europe/Lisbon"
|
|
397
|
+
[presets]="windows"
|
|
398
|
+
[(value)]="scheduled"
|
|
399
|
+
></span>
|
|
400
|
+
```
|
|
401
|
+
|
|
402
|
+
### Between two dates, as one range picker
|
|
403
|
+
|
|
404
|
+
The between of a date column is one date-range-picker rather than two pickers: it says the run length while it is drawn, takes the ends in either order and carries your presets as a template of slDateRangePickerPreset buttons. The descriptor is unchanged — between, an ISO day and another — so a saved view written with two pickers opens in the range picker.
|
|
405
|
+
|
|
406
|
+
Excerpt — not a complete module
|
|
407
|
+
|
|
408
|
+
```html
|
|
409
|
+
<ng-template #presets>
|
|
410
|
+
<button slDateRangePickerPreset [range]="september">September</button>
|
|
411
|
+
<button slDateRangePickerPreset [range]="quarter">Q4</button>
|
|
412
|
+
</ng-template>
|
|
413
|
+
<span slTableDateFilter columnLabel="due" [presets]="presets" [(value)]="dueAt"></span>
|
|
414
|
+
```
|
|
415
|
+
|
|
416
|
+
### A set typed as chips
|
|
417
|
+
|
|
418
|
+
operand of tags draws tags-input where the checkbox list stood, for a list too long to tick. With options, they are a native datalist of suggestions and a typed value outside them is refused; without options any value is admitted. The chips hold the same readonly string[] the list held, so the operator stays anyOf or noneOf and a saved view is read by either operand.
|
|
419
|
+
|
|
420
|
+
Excerpt — not a complete module
|
|
421
|
+
|
|
422
|
+
```html
|
|
423
|
+
<span
|
|
424
|
+
slTableSetFilter
|
|
425
|
+
columnLabel="client"
|
|
426
|
+
operand="tags"
|
|
427
|
+
[options]="clients"
|
|
428
|
+
[(value)]="client"
|
|
429
|
+
></span>
|
|
430
|
+
<span slTableSetFilter columnLabel="invoice" operand="tags" [(value)]="invoice"></span>
|
|
431
|
+
```
|
|
432
|
+
|
|
433
|
+
### A plain control in a cell
|
|
434
|
+
|
|
435
|
+
A cell whose child is a plain control gives up its inset: padding goes to zero and the control reads the cell padding and the row height through the control tokens, so the edited value stands where the read value stood and the row does not grow. The rule names the fourteen plain field families and nothing else. The control width is its own, as in a form.
|
|
436
|
+
|
|
437
|
+
Example
|
|
438
|
+
|
|
439
|
+
```ts
|
|
440
|
+
import { Component, signal } from '@angular/core';
|
|
441
|
+
import { SlNumberField, SlNumberFieldInput } from '@slotted/angular/number-field';
|
|
442
|
+
import { SlSelect, SlSelectItem, type SelectSelection } from '@slotted/angular/select';
|
|
443
|
+
import {
|
|
444
|
+
SlTable,
|
|
445
|
+
SlTableBody,
|
|
446
|
+
SlTableCell,
|
|
447
|
+
SlTableColumnHeader,
|
|
448
|
+
SlTableContent,
|
|
449
|
+
SlTableHead,
|
|
450
|
+
SlTableRow,
|
|
451
|
+
SlTableRowHeader,
|
|
452
|
+
} from '@slotted/angular/table';
|
|
453
|
+
|
|
454
|
+
const BINS = ['A-04', 'A-07', 'B-12', 'C-01'];
|
|
455
|
+
|
|
456
|
+
const STOCK = [
|
|
457
|
+
{ sku: 'PRD-0412', product: 'Chai', counted: 390, bin: 'A-04' },
|
|
458
|
+
{ sku: 'PRD-0413', product: 'Chang', counted: 170, bin: 'A-04' },
|
|
459
|
+
{ sku: 'PRD-0414', product: 'Aniseed Syrup', counted: 130, bin: 'B-12' },
|
|
460
|
+
{ sku: 'PRD-0415', product: "Chef Anton's Cajun Seasoning", counted: 53, bin: 'C-01' },
|
|
461
|
+
];
|
|
462
|
+
|
|
463
|
+
type Line = (typeof STOCK)[number];
|
|
464
|
+
|
|
465
|
+
@Component({
|
|
466
|
+
selector: 'app-table-editing',
|
|
467
|
+
imports: [
|
|
468
|
+
SlNumberField,
|
|
469
|
+
SlNumberFieldInput,
|
|
470
|
+
SlSelect,
|
|
471
|
+
SlSelectItem,
|
|
472
|
+
SlTable,
|
|
473
|
+
SlTableBody,
|
|
474
|
+
SlTableCell,
|
|
475
|
+
SlTableColumnHeader,
|
|
476
|
+
SlTableContent,
|
|
477
|
+
SlTableHead,
|
|
478
|
+
SlTableRow,
|
|
479
|
+
SlTableRowHeader,
|
|
480
|
+
],
|
|
481
|
+
template: `
|
|
482
|
+
<div slTable [columns]="4">
|
|
483
|
+
<div slTableContent aria-label="Stock take, Reno">
|
|
484
|
+
<thead slTableHead>
|
|
485
|
+
<tr slTableRow>
|
|
486
|
+
<th slTableColumnHeader>SKU</th>
|
|
487
|
+
<th slTableColumnHeader>Product</th>
|
|
488
|
+
<th slTableColumnHeader numeric>Counted</th>
|
|
489
|
+
<th slTableColumnHeader>Bin</th>
|
|
490
|
+
</tr>
|
|
491
|
+
</thead>
|
|
492
|
+
<tbody slTableBody>
|
|
493
|
+
@for (line of lines(); track line.sku) {
|
|
494
|
+
<tr slTableRow [value]="line.sku">
|
|
495
|
+
<th slTableRowHeader text="nowrap">{{ line.sku }}</th>
|
|
496
|
+
<td slTableCell>{{ line.product }}</td>
|
|
497
|
+
<td slTableCell numeric>
|
|
498
|
+
<div slNumberField size="sm" stepper="none" variant="plain">
|
|
499
|
+
<input
|
|
500
|
+
slNumberFieldInput
|
|
501
|
+
min="0"
|
|
502
|
+
[attr.aria-label]="'Counted for ' + line.sku"
|
|
503
|
+
[value]="line.counted"
|
|
504
|
+
(valueChange)="update(line.sku, { counted: $event.value ?? 0 })"
|
|
505
|
+
/>
|
|
506
|
+
</div>
|
|
507
|
+
</td>
|
|
508
|
+
<td slTableCell>
|
|
509
|
+
<sl-select
|
|
510
|
+
size="sm"
|
|
511
|
+
variant="plain"
|
|
512
|
+
[aria-label]="'Bin of ' + line.sku"
|
|
513
|
+
[value]="line.bin"
|
|
514
|
+
(valueChange)="setBin(line.sku, $event)"
|
|
515
|
+
>
|
|
516
|
+
@for (bin of bins; track bin) {
|
|
517
|
+
<sl-select-item [value]="bin">{{ bin }}</sl-select-item>
|
|
518
|
+
}
|
|
519
|
+
</sl-select>
|
|
520
|
+
</td>
|
|
521
|
+
</tr>
|
|
522
|
+
}
|
|
523
|
+
</tbody>
|
|
524
|
+
</div>
|
|
525
|
+
</div>
|
|
526
|
+
`,
|
|
527
|
+
})
|
|
528
|
+
export class TableEditing {
|
|
529
|
+
readonly bins = BINS;
|
|
530
|
+
readonly lines = signal<readonly Line[]>(STOCK);
|
|
531
|
+
|
|
532
|
+
setBin(sku: string, bin: SelectSelection): void {
|
|
533
|
+
if (typeof bin === 'string') this.update(sku, { bin });
|
|
534
|
+
}
|
|
535
|
+
|
|
536
|
+
update(sku: string, change: Partial<Line>): void {
|
|
537
|
+
this.lines.update((current) =>
|
|
538
|
+
current.map((line) => (line.sku === sku ? { ...line, ...change } : line)),
|
|
539
|
+
);
|
|
540
|
+
}
|
|
541
|
+
}
|
|
542
|
+
```
|
|
543
|
+
|
|
544
|
+
### Choosing records, and what all means
|
|
545
|
+
|
|
546
|
+
Hold Shift and press a second checkbox to take everything between. The header checkbox covers the rows in the DOM and says how many in its own name — a selection over a whole result set is a decision only your query can make.
|
|
547
|
+
|
|
548
|
+
Example
|
|
549
|
+
|
|
550
|
+
```ts
|
|
551
|
+
import { Component, computed, signal } from '@angular/core';
|
|
552
|
+
import {
|
|
553
|
+
SlTable,
|
|
554
|
+
SlTableBody,
|
|
555
|
+
SlTableCell,
|
|
556
|
+
SlTableColumnHeader,
|
|
557
|
+
SlTableContent,
|
|
558
|
+
SlTableFooter,
|
|
559
|
+
SlTableHead,
|
|
560
|
+
SlTableRow,
|
|
561
|
+
SlTableRowHeader,
|
|
562
|
+
SlTableSelect,
|
|
563
|
+
SlTableSelectAll,
|
|
564
|
+
} from '@slotted/angular/table';
|
|
565
|
+
import { SlText } from '@slotted/angular/typography';
|
|
566
|
+
|
|
567
|
+
const USD = new Intl.NumberFormat('en-US', { currency: 'USD', style: 'currency' });
|
|
568
|
+
|
|
569
|
+
const INVOICES = [
|
|
570
|
+
{ id: 'INV-2041', customer: 'Alfreds Futterkiste', status: 'Overdue', amount: 1240 },
|
|
571
|
+
{ id: 'INV-2042', customer: 'Great Lakes Food Market', status: 'Overdue', amount: 18402.75 },
|
|
572
|
+
{ id: 'INV-2043', customer: 'Hanari Carnes', status: 'Draft', amount: 86.4 },
|
|
573
|
+
{ id: 'INV-2044', customer: 'Island Trading', status: 'Sent', amount: 2310 },
|
|
574
|
+
{ id: 'INV-2045', customer: 'Lonesome Pine Restaurant', status: 'Sent', amount: 645.2 },
|
|
575
|
+
];
|
|
576
|
+
|
|
577
|
+
@Component({
|
|
578
|
+
selector: 'app-table-selection',
|
|
579
|
+
imports: [
|
|
580
|
+
SlTable,
|
|
581
|
+
SlTableBody,
|
|
582
|
+
SlTableCell,
|
|
583
|
+
SlTableColumnHeader,
|
|
584
|
+
SlTableContent,
|
|
585
|
+
SlTableFooter,
|
|
586
|
+
SlTableHead,
|
|
587
|
+
SlTableRow,
|
|
588
|
+
SlTableRowHeader,
|
|
589
|
+
SlTableSelect,
|
|
590
|
+
SlTableSelectAll,
|
|
591
|
+
SlText,
|
|
592
|
+
],
|
|
593
|
+
template: `
|
|
594
|
+
<div slTable [columns]="5" selectionMode="multiple" [(value)]="chosen">
|
|
595
|
+
<div slTableContent aria-label="Invoices to send reminders for">
|
|
596
|
+
<thead slTableHead>
|
|
597
|
+
<tr slTableRow>
|
|
598
|
+
<th slTableSelectAll></th>
|
|
599
|
+
<th slTableColumnHeader>Invoice</th>
|
|
600
|
+
<th slTableColumnHeader>Customer</th>
|
|
601
|
+
<th slTableColumnHeader>Status</th>
|
|
602
|
+
<th slTableColumnHeader numeric>Amount</th>
|
|
603
|
+
</tr>
|
|
604
|
+
</thead>
|
|
605
|
+
<tbody slTableBody>
|
|
606
|
+
@for (invoice of invoices; track invoice.id) {
|
|
607
|
+
<tr slTableRow [value]="invoice.id" [disabled]="invoice.status === 'Draft'">
|
|
608
|
+
<td slTableSelect></td>
|
|
609
|
+
<th slTableRowHeader text="nowrap">{{ invoice.id }}</th>
|
|
610
|
+
<td slTableCell>{{ invoice.customer }}</td>
|
|
611
|
+
<td slTableCell>{{ invoice.status }}</td>
|
|
612
|
+
<td slTableCell numeric>{{ usd.format(invoice.amount) }}</td>
|
|
613
|
+
</tr>
|
|
614
|
+
}
|
|
615
|
+
</tbody>
|
|
616
|
+
</div>
|
|
617
|
+
<div slTableFooter>
|
|
618
|
+
<span slText size="sm" tone="muted"
|
|
619
|
+
>{{ chosen().length }} selected · {{ usd.format(total()) }}</span
|
|
620
|
+
>
|
|
621
|
+
</div>
|
|
622
|
+
</div>
|
|
623
|
+
`,
|
|
624
|
+
})
|
|
625
|
+
export class TableSelection {
|
|
626
|
+
readonly invoices = INVOICES;
|
|
627
|
+
readonly usd = USD;
|
|
628
|
+
readonly chosen = signal<readonly string[]>(['INV-2041']);
|
|
629
|
+
readonly total = computed(() =>
|
|
630
|
+
INVOICES.filter((invoice) => this.chosen().includes(invoice.id)).reduce(
|
|
631
|
+
(sum, invoice) => sum + invoice.amount,
|
|
632
|
+
0,
|
|
633
|
+
),
|
|
634
|
+
);
|
|
635
|
+
}
|
|
636
|
+
```
|
|
637
|
+
|
|
638
|
+
### A record with more to say
|
|
639
|
+
|
|
640
|
+
The expander is the Disclosure pattern: a button carrying aria-expanded and naming the row it opens. Control flow in the template keeps a closed detail out of the DOM, which is the one asymmetry with React and belongs to the frameworks rather than the family.
|
|
641
|
+
|
|
642
|
+
Example
|
|
643
|
+
|
|
644
|
+
```ts
|
|
645
|
+
import { Component, signal } from '@angular/core';
|
|
646
|
+
import {
|
|
647
|
+
SlTable,
|
|
648
|
+
SlTableBody,
|
|
649
|
+
SlTableCell,
|
|
650
|
+
SlTableColumnHeader,
|
|
651
|
+
SlTableContent,
|
|
652
|
+
SlTableDetail,
|
|
653
|
+
SlTableExpander,
|
|
654
|
+
SlTableHead,
|
|
655
|
+
SlTableRow,
|
|
656
|
+
SlTableRowHeader,
|
|
657
|
+
} from '@slotted/angular/table';
|
|
658
|
+
|
|
659
|
+
const USD = new Intl.NumberFormat('en-US', { currency: 'USD', style: 'currency' });
|
|
660
|
+
|
|
661
|
+
const RETURNS = [
|
|
662
|
+
{
|
|
663
|
+
id: 'RMA-0811',
|
|
664
|
+
order: 'SO-10398',
|
|
665
|
+
customer: 'Ernst Handel',
|
|
666
|
+
refund: 214.5,
|
|
667
|
+
detail:
|
|
668
|
+
'Two cases of Chang arrived crushed. Carrier claim filed with UPS on Sep 24; refund issued to the original card.',
|
|
669
|
+
},
|
|
670
|
+
{
|
|
671
|
+
id: 'RMA-0812',
|
|
672
|
+
order: 'SO-10402',
|
|
673
|
+
customer: 'QUICK-Stop',
|
|
674
|
+
refund: 58,
|
|
675
|
+
detail:
|
|
676
|
+
'Wrong flavour shipped. Replacement sent from Columbus; the returned jar goes back to stock after inspection.',
|
|
677
|
+
},
|
|
678
|
+
{
|
|
679
|
+
id: 'RMA-0813',
|
|
680
|
+
order: 'SO-10407',
|
|
681
|
+
customer: 'Hanari Carnes',
|
|
682
|
+
refund: 1120,
|
|
683
|
+
detail:
|
|
684
|
+
'Order cancelled after dispatch. Pallet returned to Savannah unopened; restocking fee waived by account manager.',
|
|
685
|
+
},
|
|
686
|
+
];
|
|
687
|
+
|
|
688
|
+
@Component({
|
|
689
|
+
selector: 'app-table-expansion',
|
|
690
|
+
imports: [
|
|
691
|
+
SlTable,
|
|
692
|
+
SlTableBody,
|
|
693
|
+
SlTableCell,
|
|
694
|
+
SlTableColumnHeader,
|
|
695
|
+
SlTableContent,
|
|
696
|
+
SlTableDetail,
|
|
697
|
+
SlTableExpander,
|
|
698
|
+
SlTableHead,
|
|
699
|
+
SlTableRow,
|
|
700
|
+
SlTableRowHeader,
|
|
701
|
+
],
|
|
702
|
+
template: `
|
|
703
|
+
<div slTable [columns]="5" [(expanded)]="expanded">
|
|
704
|
+
<div slTableContent aria-label="Returns">
|
|
705
|
+
<thead slTableHead>
|
|
706
|
+
<tr slTableRow>
|
|
707
|
+
<th slTableColumnHeader></th>
|
|
708
|
+
<th slTableColumnHeader>Return</th>
|
|
709
|
+
<th slTableColumnHeader>Order</th>
|
|
710
|
+
<th slTableColumnHeader>Customer</th>
|
|
711
|
+
<th slTableColumnHeader numeric>Refund</th>
|
|
712
|
+
</tr>
|
|
713
|
+
</thead>
|
|
714
|
+
<tbody slTableBody>
|
|
715
|
+
@for (item of returns; track item.id) {
|
|
716
|
+
<tr slTableRow [value]="item.id" #row="slTableRow">
|
|
717
|
+
<td slTableCell><button slTableExpander></button></td>
|
|
718
|
+
<th slTableRowHeader text="nowrap">{{ item.id }}</th>
|
|
719
|
+
<td slTableCell>{{ item.order }}</td>
|
|
720
|
+
<td slTableCell>{{ item.customer }}</td>
|
|
721
|
+
<td slTableCell numeric>{{ usd.format(item.refund) }}</td>
|
|
722
|
+
</tr>
|
|
723
|
+
@if (row.expanded()) {
|
|
724
|
+
<tr slTableDetail [value]="item.id">
|
|
725
|
+
{{
|
|
726
|
+
item.detail
|
|
727
|
+
}}
|
|
728
|
+
</tr>
|
|
729
|
+
}
|
|
730
|
+
}
|
|
731
|
+
</tbody>
|
|
732
|
+
</div>
|
|
733
|
+
</div>
|
|
734
|
+
`,
|
|
735
|
+
})
|
|
736
|
+
export class TableExpansion {
|
|
737
|
+
readonly returns = RETURNS;
|
|
738
|
+
readonly usd = USD;
|
|
739
|
+
readonly expanded = signal<readonly string[]>(['RMA-0811']);
|
|
740
|
+
}
|
|
741
|
+
```
|
|
742
|
+
|
|
743
|
+
### A header, a summary and a column that stay
|
|
744
|
+
|
|
745
|
+
stickyHeader holds the head against the top of the scroller and stickyFooter holds the summary against the bottom of it, so the total is on screen at the first row and the last. stickyTo says which box that is: this table own scroller, or whatever scrolls outside it. A pinned column darkens its edge exactly while something is hidden under it, and all of it mirrors in a right-to-left document.
|
|
746
|
+
|
|
747
|
+
Example
|
|
748
|
+
|
|
749
|
+
```ts
|
|
750
|
+
import { Component } from '@angular/core';
|
|
751
|
+
import {
|
|
752
|
+
SlTable,
|
|
753
|
+
SlTableBody,
|
|
754
|
+
SlTableCell,
|
|
755
|
+
SlTableColumnHeader,
|
|
756
|
+
SlTableContent,
|
|
757
|
+
SlTableHead,
|
|
758
|
+
SlTableRow,
|
|
759
|
+
SlTableRowHeader,
|
|
760
|
+
SlTableSummary,
|
|
761
|
+
} from '@slotted/angular/table';
|
|
762
|
+
|
|
763
|
+
const USD = new Intl.NumberFormat('en-US', { currency: 'USD', style: 'currency' });
|
|
764
|
+
|
|
765
|
+
const CUSTOMERS = [
|
|
766
|
+
'Alfreds Futterkiste',
|
|
767
|
+
"Bon app'",
|
|
768
|
+
'Ernst Handel',
|
|
769
|
+
'Folk och fä HB',
|
|
770
|
+
'Hanari Carnes',
|
|
771
|
+
'Island Trading',
|
|
772
|
+
'QUICK-Stop',
|
|
773
|
+
'Wartian Herkku',
|
|
774
|
+
];
|
|
775
|
+
const WAREHOUSES = ['Reno', 'Columbus', 'Savannah'];
|
|
776
|
+
|
|
777
|
+
const ORDERS = Array.from({ length: 30 }, (_, index) => ({
|
|
778
|
+
id: `SO-${10400 + index}`,
|
|
779
|
+
customer: CUSTOMERS[index % CUSTOMERS.length],
|
|
780
|
+
warehouse: WAREHOUSES[index % WAREHOUSES.length],
|
|
781
|
+
total: 180 + ((index * 397) % 2400),
|
|
782
|
+
}));
|
|
783
|
+
|
|
784
|
+
@Component({
|
|
785
|
+
selector: 'app-table-sticky',
|
|
786
|
+
imports: [
|
|
787
|
+
SlTable,
|
|
788
|
+
SlTableBody,
|
|
789
|
+
SlTableCell,
|
|
790
|
+
SlTableColumnHeader,
|
|
791
|
+
SlTableContent,
|
|
792
|
+
SlTableHead,
|
|
793
|
+
SlTableRow,
|
|
794
|
+
SlTableRowHeader,
|
|
795
|
+
SlTableSummary,
|
|
796
|
+
],
|
|
797
|
+
template: `
|
|
798
|
+
<div slTable [columns]="4" stickyFooter stickyHeader>
|
|
799
|
+
<div slTableContent aria-label="September orders" style="max-block-size: 20rem">
|
|
800
|
+
<thead slTableHead>
|
|
801
|
+
<tr slTableRow>
|
|
802
|
+
<th slTableColumnHeader>Order</th>
|
|
803
|
+
<th slTableColumnHeader>Customer</th>
|
|
804
|
+
<th slTableColumnHeader>Warehouse</th>
|
|
805
|
+
<th slTableColumnHeader numeric>Total</th>
|
|
806
|
+
</tr>
|
|
807
|
+
</thead>
|
|
808
|
+
<tbody slTableBody>
|
|
809
|
+
@for (order of orders; track order.id) {
|
|
810
|
+
<tr slTableRow [value]="order.id">
|
|
811
|
+
<th slTableRowHeader text="nowrap">{{ order.id }}</th>
|
|
812
|
+
<td slTableCell>{{ order.customer }}</td>
|
|
813
|
+
<td slTableCell>{{ order.warehouse }}</td>
|
|
814
|
+
<td slTableCell numeric>{{ usd.format(order.total) }}</td>
|
|
815
|
+
</tr>
|
|
816
|
+
}
|
|
817
|
+
</tbody>
|
|
818
|
+
<tfoot slTableSummary>
|
|
819
|
+
<tr slTableRow>
|
|
820
|
+
<td slTableCell [attr.colspan]="3">{{ orders.length }} orders</td>
|
|
821
|
+
<td slTableCell numeric>{{ usd.format(total) }}</td>
|
|
822
|
+
</tr>
|
|
823
|
+
</tfoot>
|
|
824
|
+
</div>
|
|
825
|
+
</div>
|
|
826
|
+
`,
|
|
827
|
+
})
|
|
828
|
+
export class TableSticky {
|
|
829
|
+
readonly orders = ORDERS;
|
|
830
|
+
readonly total = ORDERS.reduce((sum, order) => sum + order.total, 0);
|
|
831
|
+
readonly usd = USD;
|
|
832
|
+
}
|
|
833
|
+
```
|
|
834
|
+
|
|
835
|
+
### Wider than the space it has
|
|
836
|
+
|
|
837
|
+
The scroller takes a tab stop, a role and a name only while it overflows, so a table that fits costs a keyboard reader nothing. Tab to it and the arrow keys, Page keys, Home and End all scroll it.
|
|
838
|
+
|
|
839
|
+
Example
|
|
840
|
+
|
|
841
|
+
```ts
|
|
842
|
+
import { Component } from '@angular/core';
|
|
843
|
+
import {
|
|
844
|
+
SlTable,
|
|
845
|
+
SlTableBody,
|
|
846
|
+
SlTableCell,
|
|
847
|
+
SlTableColumnHeader,
|
|
848
|
+
SlTableContent,
|
|
849
|
+
SlTableHead,
|
|
850
|
+
SlTableRow,
|
|
851
|
+
SlTableRowHeader,
|
|
852
|
+
} from '@slotted/angular/table';
|
|
853
|
+
|
|
854
|
+
const USD = new Intl.NumberFormat('en-US', { currency: 'USD', style: 'currency' });
|
|
855
|
+
|
|
856
|
+
const SHIPMENTS = [
|
|
857
|
+
{
|
|
858
|
+
id: 'SH-3301',
|
|
859
|
+
order: 'SO-10421',
|
|
860
|
+
customer: 'Alfreds Futterkiste',
|
|
861
|
+
origin: 'Reno, NV',
|
|
862
|
+
destination: 'Berlin, DE',
|
|
863
|
+
carrier: 'UPS Worldwide',
|
|
864
|
+
shipped: 'Sep 28, 2026',
|
|
865
|
+
cost: 412.8,
|
|
866
|
+
},
|
|
867
|
+
{
|
|
868
|
+
id: 'SH-3302',
|
|
869
|
+
order: 'SO-10422',
|
|
870
|
+
customer: "Bon app'",
|
|
871
|
+
origin: 'Columbus, OH',
|
|
872
|
+
destination: 'Marseille, FR',
|
|
873
|
+
carrier: 'FedEx International',
|
|
874
|
+
shipped: 'Sep 29, 2026',
|
|
875
|
+
cost: 288.15,
|
|
876
|
+
},
|
|
877
|
+
{
|
|
878
|
+
id: 'SH-3303',
|
|
879
|
+
order: 'SO-10423',
|
|
880
|
+
customer: 'Ernst Handel',
|
|
881
|
+
origin: 'Savannah, GA',
|
|
882
|
+
destination: 'Graz, AT',
|
|
883
|
+
carrier: 'DHL Express',
|
|
884
|
+
shipped: 'Sep 29, 2026',
|
|
885
|
+
cost: 506.4,
|
|
886
|
+
},
|
|
887
|
+
{
|
|
888
|
+
id: 'SH-3304',
|
|
889
|
+
order: 'SO-10425',
|
|
890
|
+
customer: 'QUICK-Stop',
|
|
891
|
+
origin: 'Columbus, OH',
|
|
892
|
+
destination: 'Cunewalde, DE',
|
|
893
|
+
carrier: 'UPS Worldwide',
|
|
894
|
+
shipped: 'Sep 30, 2026',
|
|
895
|
+
cost: 347.9,
|
|
896
|
+
},
|
|
897
|
+
];
|
|
898
|
+
|
|
899
|
+
@Component({
|
|
900
|
+
selector: 'app-table-scroll',
|
|
901
|
+
imports: [
|
|
902
|
+
SlTable,
|
|
903
|
+
SlTableBody,
|
|
904
|
+
SlTableCell,
|
|
905
|
+
SlTableColumnHeader,
|
|
906
|
+
SlTableContent,
|
|
907
|
+
SlTableHead,
|
|
908
|
+
SlTableRow,
|
|
909
|
+
SlTableRowHeader,
|
|
910
|
+
],
|
|
911
|
+
template: `
|
|
912
|
+
<div slTable [columns]="8">
|
|
913
|
+
<div slTableContent aria-label="International shipments">
|
|
914
|
+
<thead slTableHead>
|
|
915
|
+
<tr slTableRow>
|
|
916
|
+
<th slTableColumnHeader sticky="start" text="nowrap">Shipment</th>
|
|
917
|
+
<th slTableColumnHeader text="nowrap">Order</th>
|
|
918
|
+
<th slTableColumnHeader text="nowrap">Customer</th>
|
|
919
|
+
<th slTableColumnHeader text="nowrap">Origin</th>
|
|
920
|
+
<th slTableColumnHeader text="nowrap">Destination</th>
|
|
921
|
+
<th slTableColumnHeader text="nowrap">Carrier</th>
|
|
922
|
+
<th slTableColumnHeader text="nowrap">Shipped</th>
|
|
923
|
+
<th slTableColumnHeader numeric text="nowrap">Cost</th>
|
|
924
|
+
</tr>
|
|
925
|
+
</thead>
|
|
926
|
+
<tbody slTableBody>
|
|
927
|
+
@for (shipment of shipments; track shipment.id) {
|
|
928
|
+
<tr slTableRow [value]="shipment.id">
|
|
929
|
+
<th slTableRowHeader sticky="start" text="nowrap">{{ shipment.id }}</th>
|
|
930
|
+
<td slTableCell text="nowrap">{{ shipment.order }}</td>
|
|
931
|
+
<td slTableCell text="nowrap">{{ shipment.customer }}</td>
|
|
932
|
+
<td slTableCell text="nowrap">{{ shipment.origin }}</td>
|
|
933
|
+
<td slTableCell text="nowrap">{{ shipment.destination }}</td>
|
|
934
|
+
<td slTableCell text="nowrap">{{ shipment.carrier }}</td>
|
|
935
|
+
<td slTableCell text="nowrap">{{ shipment.shipped }}</td>
|
|
936
|
+
<td slTableCell numeric>{{ usd.format(shipment.cost) }}</td>
|
|
937
|
+
</tr>
|
|
938
|
+
}
|
|
939
|
+
</tbody>
|
|
940
|
+
</div>
|
|
941
|
+
</div>
|
|
942
|
+
`,
|
|
943
|
+
})
|
|
944
|
+
export class TableScroll {
|
|
945
|
+
readonly shipments = SHIPMENTS;
|
|
946
|
+
readonly usd = USD;
|
|
947
|
+
}
|
|
948
|
+
```
|
|
949
|
+
|
|
950
|
+
### Where a value stands, and how its digits line up
|
|
951
|
+
|
|
952
|
+
Alignment is logical, so a column aligned to the end is on the right in English and on the left in Arabic. Numeric is a separate fact: it sets tabular figures, and aligns to the end unless you say otherwise.
|
|
953
|
+
|
|
954
|
+
Example
|
|
955
|
+
|
|
956
|
+
```ts
|
|
957
|
+
import { Component } from '@angular/core';
|
|
958
|
+
import {
|
|
959
|
+
SlTable,
|
|
960
|
+
SlTableBody,
|
|
961
|
+
SlTableCell,
|
|
962
|
+
SlTableColumnHeader,
|
|
963
|
+
SlTableContent,
|
|
964
|
+
SlTableHead,
|
|
965
|
+
SlTableRow,
|
|
966
|
+
SlTableRowHeader,
|
|
967
|
+
} from '@slotted/angular/table';
|
|
968
|
+
|
|
969
|
+
const USD = new Intl.NumberFormat('en-US', { currency: 'USD', style: 'currency' });
|
|
970
|
+
|
|
971
|
+
const INVOICES = [
|
|
972
|
+
{ id: 'INV-2041', customer: 'Alfreds Futterkiste', region: 'EU', due: 'Oct 4', amount: 1240 },
|
|
973
|
+
{
|
|
974
|
+
id: 'INV-2042',
|
|
975
|
+
customer: 'Great Lakes Food Market',
|
|
976
|
+
region: 'NA',
|
|
977
|
+
due: 'Oct 9',
|
|
978
|
+
amount: 18402.75,
|
|
979
|
+
},
|
|
980
|
+
{ id: 'INV-2043', customer: 'Hanari Carnes', region: 'SA', due: 'Oct 12', amount: 86.4 },
|
|
981
|
+
];
|
|
982
|
+
|
|
983
|
+
@Component({
|
|
984
|
+
selector: 'app-table-alignment',
|
|
985
|
+
imports: [
|
|
986
|
+
SlTable,
|
|
987
|
+
SlTableBody,
|
|
988
|
+
SlTableCell,
|
|
989
|
+
SlTableColumnHeader,
|
|
990
|
+
SlTableContent,
|
|
991
|
+
SlTableHead,
|
|
992
|
+
SlTableRow,
|
|
993
|
+
SlTableRowHeader,
|
|
994
|
+
],
|
|
995
|
+
template: `
|
|
996
|
+
<div slTable [columns]="4">
|
|
997
|
+
<div slTableContent aria-label="Invoices due">
|
|
998
|
+
<thead slTableHead>
|
|
999
|
+
<tr slTableRow>
|
|
1000
|
+
<th slTableColumnHeader>Customer</th>
|
|
1001
|
+
<th slTableColumnHeader align="center">Region</th>
|
|
1002
|
+
<th slTableColumnHeader align="end">Due</th>
|
|
1003
|
+
<th slTableColumnHeader numeric>Amount</th>
|
|
1004
|
+
</tr>
|
|
1005
|
+
</thead>
|
|
1006
|
+
<tbody slTableBody>
|
|
1007
|
+
@for (invoice of invoices; track invoice.id) {
|
|
1008
|
+
<tr slTableRow [value]="invoice.id">
|
|
1009
|
+
<th slTableRowHeader>{{ invoice.customer }}</th>
|
|
1010
|
+
<td slTableCell align="center">{{ invoice.region }}</td>
|
|
1011
|
+
<td slTableCell align="end">{{ invoice.due }}</td>
|
|
1012
|
+
<td slTableCell numeric>{{ usd.format(invoice.amount) }}</td>
|
|
1013
|
+
</tr>
|
|
1014
|
+
}
|
|
1015
|
+
</tbody>
|
|
1016
|
+
</div>
|
|
1017
|
+
</div>
|
|
1018
|
+
`,
|
|
1019
|
+
})
|
|
1020
|
+
export class TableAlignment {
|
|
1021
|
+
readonly invoices = INVOICES;
|
|
1022
|
+
readonly usd = USD;
|
|
1023
|
+
}
|
|
1024
|
+
```
|
|
1025
|
+
|
|
1026
|
+
### A value longer than its column
|
|
1027
|
+
|
|
1028
|
+
Wrap breaks an unbroken token — a hash, a URL, an identifier — rather than letting it set the column width. Truncate keeps one line with the whole value still in the DOM. Nowrap never breaks. None of the three removes anything.
|
|
1029
|
+
|
|
1030
|
+
Example
|
|
1031
|
+
|
|
1032
|
+
```ts
|
|
1033
|
+
import { Component } from '@angular/core';
|
|
1034
|
+
import {
|
|
1035
|
+
SlTable,
|
|
1036
|
+
SlTableBody,
|
|
1037
|
+
SlTableCell,
|
|
1038
|
+
SlTableColumnHeader,
|
|
1039
|
+
SlTableContent,
|
|
1040
|
+
SlTableHead,
|
|
1041
|
+
SlTableRow,
|
|
1042
|
+
SlTableRowHeader,
|
|
1043
|
+
} from '@slotted/angular/table';
|
|
1044
|
+
|
|
1045
|
+
const NOTES = [
|
|
1046
|
+
{
|
|
1047
|
+
id: 'SO-10421',
|
|
1048
|
+
note: 'Leave at the loading dock behind the warehouse; the front office closes at noon on Fridays.',
|
|
1049
|
+
tracking: '1Z999AA10123456784',
|
|
1050
|
+
},
|
|
1051
|
+
{
|
|
1052
|
+
id: 'SO-10422',
|
|
1053
|
+
note: 'Customer asked for the invoice to be emailed to accounts payable rather than printed.',
|
|
1054
|
+
tracking: '1Z999AA10123456785',
|
|
1055
|
+
},
|
|
1056
|
+
];
|
|
1057
|
+
|
|
1058
|
+
@Component({
|
|
1059
|
+
selector: 'app-table-text',
|
|
1060
|
+
imports: [
|
|
1061
|
+
SlTable,
|
|
1062
|
+
SlTableBody,
|
|
1063
|
+
SlTableCell,
|
|
1064
|
+
SlTableColumnHeader,
|
|
1065
|
+
SlTableContent,
|
|
1066
|
+
SlTableHead,
|
|
1067
|
+
SlTableRow,
|
|
1068
|
+
SlTableRowHeader,
|
|
1069
|
+
],
|
|
1070
|
+
template: `
|
|
1071
|
+
<div slTable [columns]="3" layout="fixed">
|
|
1072
|
+
<div slTableContent aria-label="Delivery notes">
|
|
1073
|
+
<thead slTableHead>
|
|
1074
|
+
<tr slTableRow>
|
|
1075
|
+
<th slTableColumnHeader>Order</th>
|
|
1076
|
+
<th slTableColumnHeader>Note</th>
|
|
1077
|
+
<th slTableColumnHeader>Tracking</th>
|
|
1078
|
+
</tr>
|
|
1079
|
+
</thead>
|
|
1080
|
+
<tbody slTableBody>
|
|
1081
|
+
@for (row of notes; track row.id) {
|
|
1082
|
+
<tr slTableRow [value]="row.id">
|
|
1083
|
+
<th slTableRowHeader text="nowrap">{{ row.id }}</th>
|
|
1084
|
+
<td slTableCell text="truncate">{{ row.note }}</td>
|
|
1085
|
+
<td slTableCell text="wrap">{{ row.tracking }}</td>
|
|
1086
|
+
</tr>
|
|
1087
|
+
}
|
|
1088
|
+
</tbody>
|
|
1089
|
+
</div>
|
|
1090
|
+
</div>
|
|
1091
|
+
`,
|
|
1092
|
+
})
|
|
1093
|
+
export class TableText {
|
|
1094
|
+
readonly notes = NOTES;
|
|
1095
|
+
}
|
|
1096
|
+
```
|
|
1097
|
+
|
|
1098
|
+
### The totals, and the page
|
|
1099
|
+
|
|
1100
|
+
Two different feet. The summary is a tfoot inside the table, where a total belongs beside the column it totals. The footer is a bar outside it and inside the frame, which is where the paging control goes and where it does not scroll sideways.
|
|
1101
|
+
|
|
1102
|
+
Excerpt — not a complete module
|
|
1103
|
+
|
|
1104
|
+
```html
|
|
1105
|
+
<div slTable>
|
|
1106
|
+
<div slTableContent [totalRowCount]="128">
|
|
1107
|
+
<tfoot slTableSummary>
|
|
1108
|
+
<tr slTableRow>
|
|
1109
|
+
<td slTableCell numeric>11,061.25</td>
|
|
1110
|
+
</tr>
|
|
1111
|
+
</tfoot>
|
|
1112
|
+
</div>
|
|
1113
|
+
<div slTableFooter>
|
|
1114
|
+
<span>3 of 128 invoices</span>
|
|
1115
|
+
<nav slPagination [count]="128" [pageSize]="3"></nav>
|
|
1116
|
+
</div>
|
|
1117
|
+
</div>
|
|
1118
|
+
```
|
|
1119
|
+
|
|
1120
|
+
### Nothing yet, nothing at all, and something arriving
|
|
1121
|
+
|
|
1122
|
+
A first load draws skeleton rows, so the shape is visible before the content. A refresh over rows already read writes aria-busy and dims them without moving anything — a reader looking at row forty stays there.
|
|
1123
|
+
|
|
1124
|
+
Excerpt — not a complete module
|
|
1125
|
+
|
|
1126
|
+
```html
|
|
1127
|
+
@if (loading() && rows().length === 0) {
|
|
1128
|
+
<tbody slTableLoader [skeletonRows]="5"></tbody>
|
|
1129
|
+
} @else if (rows().length === 0) {
|
|
1130
|
+
<tbody slTableBody>
|
|
1131
|
+
<tr slTableRow>
|
|
1132
|
+
<td slTableEmpty>
|
|
1133
|
+
<section slResultState status="no-results"></section>
|
|
1134
|
+
</td>
|
|
1135
|
+
</tr>
|
|
1136
|
+
</tbody>
|
|
1137
|
+
} @else {
|
|
1138
|
+
<tbody slTableBody></tbody>
|
|
1139
|
+
}
|
|
1140
|
+
```
|
|
1141
|
+
|
|
1142
|
+
### The same table, three sizes
|
|
1143
|
+
|
|
1144
|
+
The row reads the control height, the cell reads the control inset and the type reads the control step, so one theme decision retunes the rows, the buttons and the fields together. Density changes the size and never the meaning.
|
|
1145
|
+
|
|
1146
|
+
Excerpt — not a complete module
|
|
1147
|
+
|
|
1148
|
+
```html
|
|
1149
|
+
<div data-slotted-density="dense">
|
|
1150
|
+
<div slTable></div>
|
|
1151
|
+
</div>
|
|
1152
|
+
```
|
|
1153
|
+
|
|
1154
|
+
### Content the table did not choose
|
|
1155
|
+
|
|
1156
|
+
A forty-character identifier, a translated header twice as long as its English, a cell holding a tag and a link. The table is a grid of your own content, so the parts hold whatever a record needs rather than a string.
|
|
1157
|
+
|
|
1158
|
+
Example
|
|
1159
|
+
|
|
1160
|
+
```ts
|
|
1161
|
+
import { Component } from '@angular/core';
|
|
1162
|
+
import { SlAvatar } from '@slotted/angular/avatar';
|
|
1163
|
+
import { SlInline } from '@slotted/angular/inline';
|
|
1164
|
+
import { SlLink } from '@slotted/angular/link';
|
|
1165
|
+
import { SlStatusIndicator } from '@slotted/angular/status-indicator';
|
|
1166
|
+
import {
|
|
1167
|
+
SlTable,
|
|
1168
|
+
SlTableBody,
|
|
1169
|
+
SlTableCell,
|
|
1170
|
+
SlTableColumnHeader,
|
|
1171
|
+
SlTableContent,
|
|
1172
|
+
SlTableHead,
|
|
1173
|
+
SlTableRow,
|
|
1174
|
+
SlTableRowHeader,
|
|
1175
|
+
} from '@slotted/angular/table';
|
|
1176
|
+
|
|
1177
|
+
const USD = new Intl.NumberFormat('en-US', { currency: 'USD', style: 'currency' });
|
|
1178
|
+
|
|
1179
|
+
const ACCOUNTS = [
|
|
1180
|
+
{
|
|
1181
|
+
id: 'ALFKI',
|
|
1182
|
+
name: 'Alfreds Futterkiste',
|
|
1183
|
+
manager: 'Nancy Davolio',
|
|
1184
|
+
sync: 'success',
|
|
1185
|
+
syncLabel: 'In sync',
|
|
1186
|
+
balance: 1240,
|
|
1187
|
+
},
|
|
1188
|
+
{
|
|
1189
|
+
id: 'ERNSH',
|
|
1190
|
+
name: 'Ernst Handel',
|
|
1191
|
+
manager: 'Andrew Fuller',
|
|
1192
|
+
sync: 'warning',
|
|
1193
|
+
syncLabel: 'Delayed',
|
|
1194
|
+
balance: 3410.25,
|
|
1195
|
+
},
|
|
1196
|
+
{
|
|
1197
|
+
id: 'QUICK',
|
|
1198
|
+
name: 'QUICK-Stop',
|
|
1199
|
+
manager: 'Janet Leverling',
|
|
1200
|
+
sync: 'danger',
|
|
1201
|
+
syncLabel: 'Failed',
|
|
1202
|
+
balance: 2088.9,
|
|
1203
|
+
},
|
|
1204
|
+
] as const;
|
|
1205
|
+
|
|
1206
|
+
@Component({
|
|
1207
|
+
selector: 'app-table-content',
|
|
1208
|
+
imports: [
|
|
1209
|
+
SlAvatar,
|
|
1210
|
+
SlInline,
|
|
1211
|
+
SlLink,
|
|
1212
|
+
SlStatusIndicator,
|
|
1213
|
+
SlTable,
|
|
1214
|
+
SlTableBody,
|
|
1215
|
+
SlTableCell,
|
|
1216
|
+
SlTableColumnHeader,
|
|
1217
|
+
SlTableContent,
|
|
1218
|
+
SlTableHead,
|
|
1219
|
+
SlTableRow,
|
|
1220
|
+
SlTableRowHeader,
|
|
1221
|
+
],
|
|
1222
|
+
template: `
|
|
1223
|
+
<div slTable [columns]="4">
|
|
1224
|
+
<div slTableContent aria-label="Key accounts">
|
|
1225
|
+
<thead slTableHead>
|
|
1226
|
+
<tr slTableRow>
|
|
1227
|
+
<th slTableColumnHeader>Account</th>
|
|
1228
|
+
<th slTableColumnHeader>Account manager</th>
|
|
1229
|
+
<th slTableColumnHeader>ERP sync</th>
|
|
1230
|
+
<th slTableColumnHeader numeric>Balance</th>
|
|
1231
|
+
</tr>
|
|
1232
|
+
</thead>
|
|
1233
|
+
<tbody slTableBody>
|
|
1234
|
+
@for (account of accounts; track account.id) {
|
|
1235
|
+
<tr slTableRow [value]="account.id">
|
|
1236
|
+
<th slTableRowHeader text="nowrap">
|
|
1237
|
+
<a slLink [href]="'#' + account.id">{{ account.name }}</a>
|
|
1238
|
+
</th>
|
|
1239
|
+
<td slTableCell text="nowrap">
|
|
1240
|
+
<div slInline align="center" [gap]="2">
|
|
1241
|
+
<span slAvatar size="sm" [name]="account.manager"></span>
|
|
1242
|
+
{{ account.manager }}
|
|
1243
|
+
</div>
|
|
1244
|
+
</td>
|
|
1245
|
+
<td slTableCell text="nowrap">
|
|
1246
|
+
<span slStatusIndicator [status]="account.sync">{{ account.syncLabel }}</span>
|
|
1247
|
+
</td>
|
|
1248
|
+
<td slTableCell numeric>{{ usd.format(account.balance) }}</td>
|
|
1249
|
+
</tr>
|
|
1250
|
+
}
|
|
1251
|
+
</tbody>
|
|
1252
|
+
</div>
|
|
1253
|
+
</div>
|
|
1254
|
+
`,
|
|
1255
|
+
})
|
|
1256
|
+
export class TableContentExample {
|
|
1257
|
+
readonly accounts = ACCOUNTS;
|
|
1258
|
+
readonly usd = USD;
|
|
1259
|
+
}
|
|
1260
|
+
```
|
|
1261
|
+
|
|
1262
|
+
### The screen this is reached for
|
|
1263
|
+
|
|
1264
|
+
Sorting, selection with a bulk action, a filter in a header, an identifier pinned at the start and actions pinned at the end, a paging control in the footer. Every piece beside the table is another family, composed rather than built in.
|
|
1265
|
+
|
|
1266
|
+
Excerpt — not a complete module
|
|
1267
|
+
|
|
1268
|
+
```html
|
|
1269
|
+
<div
|
|
1270
|
+
slTable
|
|
1271
|
+
variant="framed"
|
|
1272
|
+
stickyHeader
|
|
1273
|
+
selectionMode="multiple"
|
|
1274
|
+
[columns]="5"
|
|
1275
|
+
[(value)]="chosen"
|
|
1276
|
+
[(sort)]="sort"
|
|
1277
|
+
>
|
|
1278
|
+
<div slTableContent [totalRowCount]="128"></div>
|
|
1279
|
+
<div slTableFooter>
|
|
1280
|
+
<nav slPagination [count]="128"></nav>
|
|
1281
|
+
</div>
|
|
1282
|
+
</div>
|
|
1283
|
+
```
|
|
1284
|
+
|
|
1285
|
+
### Setting the table once, and reaching past it
|
|
1286
|
+
|
|
1287
|
+
provideTableDefaults sets the frame and the layout for everything under that injector, provideSlotted the language, and a table that states an axis itself still wins. Every part is a directive on your own element, so nothing is wrapped that you did not write.
|
|
1288
|
+
|
|
1289
|
+
Excerpt — not a complete module
|
|
1290
|
+
|
|
1291
|
+
```ts
|
|
1292
|
+
bootstrapApplication(App, {
|
|
1293
|
+
providers: [
|
|
1294
|
+
provideTableDefaults({
|
|
1295
|
+
variant: 'framed',
|
|
1296
|
+
stickyHeader: true,
|
|
1297
|
+
}),
|
|
1298
|
+
],
|
|
1299
|
+
});
|
|
1300
|
+
```
|
|
1301
|
+
|
|
1302
|
+
### Every control is its own tab stop
|
|
1303
|
+
|
|
1304
|
+
A table is not a composite widget, so the table binds no key: Tab reaches the scroller, then each sort button, checkbox and expander in DOM order. Shift with Space on a checkbox takes the range, which is the one gesture the family adds.
|
|
1305
|
+
|
|
1306
|
+
Excerpt — not a complete module
|
|
1307
|
+
|
|
1308
|
+
```html
|
|
1309
|
+
<!-- Enter and Space activate the buttons the table renders. -->
|
|
1310
|
+
<!-- Shift + Space on a row checkbox selects from the anchor. -->
|
|
1311
|
+
<!-- The scroller answers the arrow, Page, Home and End keys. -->
|
|
1312
|
+
```
|
|
1313
|
+
|
|
1314
|
+
### What a reader hears
|
|
1315
|
+
|
|
1316
|
+
The caption names the table, scope ties every value to its column and its record, aria-sort says the order and the announcer says it changed. A paged table states aria-rowcount so row three of twenty is row three of four hundred.
|
|
1317
|
+
|
|
1318
|
+
Excerpt — not a complete module
|
|
1319
|
+
|
|
1320
|
+
```html
|
|
1321
|
+
<div slTableContent [totalRowCount]="412">
|
|
1322
|
+
<tbody slTableBody>
|
|
1323
|
+
<tr slTableRow value="INV-1042" [rowIndex]="41">
|
|
1324
|
+
<th slTableRowHeader>INV-1042</th>
|
|
1325
|
+
</tr>
|
|
1326
|
+
</tbody>
|
|
1327
|
+
</div>
|
|
1328
|
+
```
|
|
1329
|
+
|
|
1330
|
+
### empty.ts
|
|
1331
|
+
|
|
1332
|
+
Example
|
|
1333
|
+
|
|
1334
|
+
```ts
|
|
1335
|
+
import { Component } from '@angular/core';
|
|
1336
|
+
import {
|
|
1337
|
+
SlResultState,
|
|
1338
|
+
SlResultStateContent,
|
|
1339
|
+
SlResultStateDescription,
|
|
1340
|
+
SlResultStateTitle,
|
|
1341
|
+
} from '@slotted/angular/result-state';
|
|
1342
|
+
import {
|
|
1343
|
+
SlTable,
|
|
1344
|
+
SlTableBody,
|
|
1345
|
+
SlTableColumnHeader,
|
|
1346
|
+
SlTableContent,
|
|
1347
|
+
SlTableEmpty,
|
|
1348
|
+
SlTableHead,
|
|
1349
|
+
SlTableRow,
|
|
1350
|
+
} from '@slotted/angular/table';
|
|
1351
|
+
|
|
1352
|
+
@Component({
|
|
1353
|
+
selector: 'app-table-empty',
|
|
1354
|
+
imports: [
|
|
1355
|
+
SlResultState,
|
|
1356
|
+
SlResultStateContent,
|
|
1357
|
+
SlResultStateDescription,
|
|
1358
|
+
SlResultStateTitle,
|
|
1359
|
+
SlTable,
|
|
1360
|
+
SlTableBody,
|
|
1361
|
+
SlTableColumnHeader,
|
|
1362
|
+
SlTableContent,
|
|
1363
|
+
SlTableEmpty,
|
|
1364
|
+
SlTableHead,
|
|
1365
|
+
SlTableRow,
|
|
1366
|
+
],
|
|
1367
|
+
template: `
|
|
1368
|
+
<div slTable [columns]="4">
|
|
1369
|
+
<div slTableContent aria-label="Returns this week">
|
|
1370
|
+
<thead slTableHead>
|
|
1371
|
+
<tr slTableRow>
|
|
1372
|
+
<th slTableColumnHeader>Return</th>
|
|
1373
|
+
<th slTableColumnHeader>Order</th>
|
|
1374
|
+
<th slTableColumnHeader>Customer</th>
|
|
1375
|
+
<th slTableColumnHeader numeric>Refund</th>
|
|
1376
|
+
</tr>
|
|
1377
|
+
</thead>
|
|
1378
|
+
<tbody slTableBody>
|
|
1379
|
+
<tr slTableRow>
|
|
1380
|
+
<td slTableEmpty>
|
|
1381
|
+
<section slResultState status="empty">
|
|
1382
|
+
<div slResultStateContent>
|
|
1383
|
+
<h3 slResultStateTitle>No returns this week</h3>
|
|
1384
|
+
<p slResultStateDescription>
|
|
1385
|
+
Returns appear here as soon as a customer opens one from their order page.
|
|
1386
|
+
</p>
|
|
1387
|
+
</div>
|
|
1388
|
+
</section>
|
|
1389
|
+
</td>
|
|
1390
|
+
</tr>
|
|
1391
|
+
</tbody>
|
|
1392
|
+
</div>
|
|
1393
|
+
</div>
|
|
1394
|
+
`,
|
|
1395
|
+
})
|
|
1396
|
+
export class TableEmptyExample {}
|
|
1397
|
+
```
|
|
1398
|
+
|
|
1399
|
+
### loading.ts
|
|
1400
|
+
|
|
1401
|
+
Example
|
|
1402
|
+
|
|
1403
|
+
```ts
|
|
1404
|
+
import { Component } from '@angular/core';
|
|
1405
|
+
import {
|
|
1406
|
+
SlTable,
|
|
1407
|
+
SlTableColumnHeader,
|
|
1408
|
+
SlTableContent,
|
|
1409
|
+
SlTableHead,
|
|
1410
|
+
SlTableLoader,
|
|
1411
|
+
SlTableRow,
|
|
1412
|
+
} from '@slotted/angular/table';
|
|
1413
|
+
|
|
1414
|
+
@Component({
|
|
1415
|
+
selector: 'app-table-loading',
|
|
1416
|
+
imports: [SlTable, SlTableColumnHeader, SlTableContent, SlTableHead, SlTableLoader, SlTableRow],
|
|
1417
|
+
template: `
|
|
1418
|
+
<div slTable [columns]="4">
|
|
1419
|
+
<div slTableContent aria-label="Purchase orders">
|
|
1420
|
+
<thead slTableHead>
|
|
1421
|
+
<tr slTableRow>
|
|
1422
|
+
<th slTableColumnHeader>Purchase order</th>
|
|
1423
|
+
<th slTableColumnHeader>Supplier</th>
|
|
1424
|
+
<th slTableColumnHeader>Expected</th>
|
|
1425
|
+
<th slTableColumnHeader numeric>Value</th>
|
|
1426
|
+
</tr>
|
|
1427
|
+
</thead>
|
|
1428
|
+
<tbody slTableLoader [skeletonRows]="4"></tbody>
|
|
1429
|
+
</div>
|
|
1430
|
+
</div>
|
|
1431
|
+
`,
|
|
1432
|
+
})
|
|
1433
|
+
export class TableLoading {}
|
|
1434
|
+
```
|
|
1435
|
+
|
|
1436
|
+
### orders-list.ts
|
|
1437
|
+
|
|
1438
|
+
Example
|
|
1439
|
+
|
|
1440
|
+
```ts
|
|
1441
|
+
import { Component, computed, signal } from '@angular/core';
|
|
1442
|
+
import { createFilterPredicate, type SetFilter } from '@slotted/core/filter';
|
|
1443
|
+
import { SlButton } from '@slotted/angular/button';
|
|
1444
|
+
import { SlInline } from '@slotted/angular/inline';
|
|
1445
|
+
import {
|
|
1446
|
+
SlPagination,
|
|
1447
|
+
SlPaginationItems,
|
|
1448
|
+
SlPaginationNext,
|
|
1449
|
+
SlPaginationPrevious,
|
|
1450
|
+
} from '@slotted/angular/pagination';
|
|
1451
|
+
import {
|
|
1452
|
+
SlTable,
|
|
1453
|
+
SlTableBody,
|
|
1454
|
+
SlTableCell,
|
|
1455
|
+
SlTableColumnActions,
|
|
1456
|
+
SlTableColumnHeader,
|
|
1457
|
+
SlTableContent,
|
|
1458
|
+
SlTableFooter,
|
|
1459
|
+
SlTableHead,
|
|
1460
|
+
SlTableRow,
|
|
1461
|
+
SlTableRowHeader,
|
|
1462
|
+
SlTableSelect,
|
|
1463
|
+
SlTableSelectAll,
|
|
1464
|
+
SlTableSetFilter,
|
|
1465
|
+
SlTableSort,
|
|
1466
|
+
type TableSortDescriptor,
|
|
1467
|
+
} from '@slotted/angular/table';
|
|
1468
|
+
import { SlText } from '@slotted/angular/typography';
|
|
1469
|
+
|
|
1470
|
+
const USD = new Intl.NumberFormat('en-US', { currency: 'USD', style: 'currency' });
|
|
1471
|
+
|
|
1472
|
+
const CUSTOMERS = [
|
|
1473
|
+
'Alfreds Futterkiste',
|
|
1474
|
+
"Bon app'",
|
|
1475
|
+
'Ernst Handel',
|
|
1476
|
+
'Folk och fä HB',
|
|
1477
|
+
'Hanari Carnes',
|
|
1478
|
+
'Island Trading',
|
|
1479
|
+
'QUICK-Stop',
|
|
1480
|
+
];
|
|
1481
|
+
const STATUS_CYCLE = ['Processing', 'Shipped', 'On hold', 'Delivered', 'Processing'];
|
|
1482
|
+
|
|
1483
|
+
const ORDERS = Array.from({ length: 20 }, (_, index) => ({
|
|
1484
|
+
id: `SO-${10421 + index}`,
|
|
1485
|
+
customer: CUSTOMERS[index % CUSTOMERS.length],
|
|
1486
|
+
status: STATUS_CYCLE[index % STATUS_CYCLE.length],
|
|
1487
|
+
total: 140 + ((index * 733) % 4100),
|
|
1488
|
+
}));
|
|
1489
|
+
|
|
1490
|
+
type Order = (typeof ORDERS)[number];
|
|
1491
|
+
|
|
1492
|
+
const STATUSES = ['Processing', 'On hold', 'Shipped', 'Delivered'].map((value) => ({
|
|
1493
|
+
value,
|
|
1494
|
+
count: ORDERS.filter((order) => order.status === value).length,
|
|
1495
|
+
}));
|
|
1496
|
+
|
|
1497
|
+
const PAGE_SIZE = 6;
|
|
1498
|
+
|
|
1499
|
+
function sortOrders(rows: readonly Order[], sort: TableSortDescriptor | null): readonly Order[] {
|
|
1500
|
+
if (sort === null) return rows;
|
|
1501
|
+
const key = sort.column as keyof Order;
|
|
1502
|
+
const sign = sort.direction === 'ascending' ? 1 : -1;
|
|
1503
|
+
return [...rows].sort((a, b) =>
|
|
1504
|
+
typeof a[key] === 'number'
|
|
1505
|
+
? ((a[key] as number) - (b[key] as number)) * sign
|
|
1506
|
+
: String(a[key]).localeCompare(String(b[key])) * sign,
|
|
1507
|
+
);
|
|
1508
|
+
}
|
|
1509
|
+
|
|
1510
|
+
@Component({
|
|
1511
|
+
selector: 'app-table-orders-list',
|
|
1512
|
+
imports: [
|
|
1513
|
+
SlButton,
|
|
1514
|
+
SlInline,
|
|
1515
|
+
SlPagination,
|
|
1516
|
+
SlPaginationItems,
|
|
1517
|
+
SlPaginationNext,
|
|
1518
|
+
SlPaginationPrevious,
|
|
1519
|
+
SlTable,
|
|
1520
|
+
SlTableBody,
|
|
1521
|
+
SlTableCell,
|
|
1522
|
+
SlTableColumnActions,
|
|
1523
|
+
SlTableColumnHeader,
|
|
1524
|
+
SlTableContent,
|
|
1525
|
+
SlTableFooter,
|
|
1526
|
+
SlTableHead,
|
|
1527
|
+
SlTableRow,
|
|
1528
|
+
SlTableRowHeader,
|
|
1529
|
+
SlTableSelect,
|
|
1530
|
+
SlTableSelectAll,
|
|
1531
|
+
SlTableSetFilter,
|
|
1532
|
+
SlTableSort,
|
|
1533
|
+
SlText,
|
|
1534
|
+
],
|
|
1535
|
+
template: `
|
|
1536
|
+
<div slTable [columns]="5" selectionMode="multiple" [(sort)]="sort" [(value)]="chosen">
|
|
1537
|
+
<div slTableContent aria-label="Orders" [totalRowCount]="matching().length">
|
|
1538
|
+
<thead slTableHead>
|
|
1539
|
+
<tr slTableRow>
|
|
1540
|
+
<th slTableSelectAll></th>
|
|
1541
|
+
<th slTableColumnHeader column="id"><button slTableSort>Order</button></th>
|
|
1542
|
+
<th slTableColumnHeader column="customer"><button slTableSort>Customer</button></th>
|
|
1543
|
+
<th slTableColumnHeader>
|
|
1544
|
+
Status
|
|
1545
|
+
<span slTableColumnActions>
|
|
1546
|
+
<span
|
|
1547
|
+
slTableSetFilter
|
|
1548
|
+
columnLabel="status"
|
|
1549
|
+
[options]="statuses"
|
|
1550
|
+
[value]="status()"
|
|
1551
|
+
(valueChange)="filter($event)"
|
|
1552
|
+
></span>
|
|
1553
|
+
</span>
|
|
1554
|
+
</th>
|
|
1555
|
+
<th slTableColumnHeader column="total" numeric><button slTableSort>Total</button></th>
|
|
1556
|
+
</tr>
|
|
1557
|
+
</thead>
|
|
1558
|
+
<tbody slTableBody>
|
|
1559
|
+
@for (order of rows(); track order.id; let index = $index) {
|
|
1560
|
+
<tr slTableRow [value]="order.id" [rowIndex]="first() + index + 1">
|
|
1561
|
+
<td slTableSelect></td>
|
|
1562
|
+
<th slTableRowHeader text="nowrap">{{ order.id }}</th>
|
|
1563
|
+
<td slTableCell>{{ order.customer }}</td>
|
|
1564
|
+
<td slTableCell>{{ order.status }}</td>
|
|
1565
|
+
<td slTableCell numeric>{{ usd.format(order.total) }}</td>
|
|
1566
|
+
</tr>
|
|
1567
|
+
}
|
|
1568
|
+
</tbody>
|
|
1569
|
+
</div>
|
|
1570
|
+
<div slTableFooter>
|
|
1571
|
+
<div slInline align="center" [gap]="3">
|
|
1572
|
+
<span slText size="sm" tone="muted">{{ chosen().length }} selected</span>
|
|
1573
|
+
<button
|
|
1574
|
+
slButton
|
|
1575
|
+
type="button"
|
|
1576
|
+
size="sm"
|
|
1577
|
+
variant="outline"
|
|
1578
|
+
[disabled]="chosen().length === 0"
|
|
1579
|
+
>
|
|
1580
|
+
Print packing slips
|
|
1581
|
+
</button>
|
|
1582
|
+
</div>
|
|
1583
|
+
<nav
|
|
1584
|
+
slPagination
|
|
1585
|
+
[count]="matching().length"
|
|
1586
|
+
[page]="page()"
|
|
1587
|
+
[pageSize]="pageSize"
|
|
1588
|
+
(pageChange)="page.set($event.value)"
|
|
1589
|
+
>
|
|
1590
|
+
<button slPaginationPrevious type="button"></button>
|
|
1591
|
+
<sl-pagination-items></sl-pagination-items>
|
|
1592
|
+
<button slPaginationNext type="button"></button>
|
|
1593
|
+
</nav>
|
|
1594
|
+
</div>
|
|
1595
|
+
</div>
|
|
1596
|
+
`,
|
|
1597
|
+
})
|
|
1598
|
+
export class TableOrdersList {
|
|
1599
|
+
readonly statuses = STATUSES;
|
|
1600
|
+
readonly pageSize = PAGE_SIZE;
|
|
1601
|
+
readonly usd = USD;
|
|
1602
|
+
readonly sort = signal<TableSortDescriptor | null>({ column: 'id', direction: 'descending' });
|
|
1603
|
+
readonly status = signal<SetFilter | null>(null);
|
|
1604
|
+
readonly chosen = signal<readonly string[]>([]);
|
|
1605
|
+
readonly page = signal(1);
|
|
1606
|
+
|
|
1607
|
+
readonly matching = computed(() => {
|
|
1608
|
+
const keep = createFilterPredicate(this.status());
|
|
1609
|
+
return sortOrders(
|
|
1610
|
+
ORDERS.filter((order) => keep(order.status)),
|
|
1611
|
+
this.sort(),
|
|
1612
|
+
);
|
|
1613
|
+
});
|
|
1614
|
+
readonly first = computed(() => (this.page() - 1) * PAGE_SIZE);
|
|
1615
|
+
readonly rows = computed(() => this.matching().slice(this.first(), this.first() + PAGE_SIZE));
|
|
1616
|
+
|
|
1617
|
+
filter(next: SetFilter | null): void {
|
|
1618
|
+
this.status.set(next);
|
|
1619
|
+
this.page.set(1);
|
|
1620
|
+
}
|
|
1621
|
+
}
|
|
1622
|
+
```
|
|
1623
|
+
|
|
1624
|
+
### pagination.ts
|
|
1625
|
+
|
|
1626
|
+
Example
|
|
1627
|
+
|
|
1628
|
+
```ts
|
|
1629
|
+
import { Component, computed, signal } from '@angular/core';
|
|
1630
|
+
import {
|
|
1631
|
+
SlPagination,
|
|
1632
|
+
SlPaginationItems,
|
|
1633
|
+
SlPaginationNext,
|
|
1634
|
+
SlPaginationPrevious,
|
|
1635
|
+
} from '@slotted/angular/pagination';
|
|
1636
|
+
import {
|
|
1637
|
+
SlTable,
|
|
1638
|
+
SlTableBody,
|
|
1639
|
+
SlTableCell,
|
|
1640
|
+
SlTableColumnHeader,
|
|
1641
|
+
SlTableContent,
|
|
1642
|
+
SlTableFooter,
|
|
1643
|
+
SlTableHead,
|
|
1644
|
+
SlTableRow,
|
|
1645
|
+
SlTableRowHeader,
|
|
1646
|
+
} from '@slotted/angular/table';
|
|
1647
|
+
import { SlText } from '@slotted/angular/typography';
|
|
1648
|
+
|
|
1649
|
+
const USD = new Intl.NumberFormat('en-US', { currency: 'USD', style: 'currency' });
|
|
1650
|
+
|
|
1651
|
+
const CUSTOMERS = [
|
|
1652
|
+
'Alfreds Futterkiste',
|
|
1653
|
+
"Bon app'",
|
|
1654
|
+
'Ernst Handel',
|
|
1655
|
+
'Folk och fä HB',
|
|
1656
|
+
'Hanari Carnes',
|
|
1657
|
+
'Island Trading',
|
|
1658
|
+
'QUICK-Stop',
|
|
1659
|
+
];
|
|
1660
|
+
|
|
1661
|
+
const INVOICES = Array.from({ length: 23 }, (_, index) => ({
|
|
1662
|
+
id: `INV-${2041 + index}`,
|
|
1663
|
+
customer: CUSTOMERS[index % CUSTOMERS.length],
|
|
1664
|
+
amount: 120 + ((index * 613) % 3900),
|
|
1665
|
+
}));
|
|
1666
|
+
|
|
1667
|
+
const PAGE_SIZE = 5;
|
|
1668
|
+
|
|
1669
|
+
@Component({
|
|
1670
|
+
selector: 'app-table-pagination',
|
|
1671
|
+
imports: [
|
|
1672
|
+
SlPagination,
|
|
1673
|
+
SlPaginationItems,
|
|
1674
|
+
SlPaginationNext,
|
|
1675
|
+
SlPaginationPrevious,
|
|
1676
|
+
SlTable,
|
|
1677
|
+
SlTableBody,
|
|
1678
|
+
SlTableCell,
|
|
1679
|
+
SlTableColumnHeader,
|
|
1680
|
+
SlTableContent,
|
|
1681
|
+
SlTableFooter,
|
|
1682
|
+
SlTableHead,
|
|
1683
|
+
SlTableRow,
|
|
1684
|
+
SlTableRowHeader,
|
|
1685
|
+
SlText,
|
|
1686
|
+
],
|
|
1687
|
+
template: `
|
|
1688
|
+
<div slTable [columns]="3">
|
|
1689
|
+
<div slTableContent aria-label="Invoices" [totalRowCount]="invoices.length">
|
|
1690
|
+
<thead slTableHead>
|
|
1691
|
+
<tr slTableRow>
|
|
1692
|
+
<th slTableColumnHeader>Invoice</th>
|
|
1693
|
+
<th slTableColumnHeader>Customer</th>
|
|
1694
|
+
<th slTableColumnHeader numeric>Amount</th>
|
|
1695
|
+
</tr>
|
|
1696
|
+
</thead>
|
|
1697
|
+
<tbody slTableBody>
|
|
1698
|
+
@for (invoice of rows(); track invoice.id; let index = $index) {
|
|
1699
|
+
<tr slTableRow [value]="invoice.id" [rowIndex]="first() + index + 1">
|
|
1700
|
+
<th slTableRowHeader text="nowrap">{{ invoice.id }}</th>
|
|
1701
|
+
<td slTableCell>{{ invoice.customer }}</td>
|
|
1702
|
+
<td slTableCell numeric>{{ usd.format(invoice.amount) }}</td>
|
|
1703
|
+
</tr>
|
|
1704
|
+
}
|
|
1705
|
+
</tbody>
|
|
1706
|
+
</div>
|
|
1707
|
+
<div slTableFooter>
|
|
1708
|
+
<span slText size="sm" tone="muted"
|
|
1709
|
+
>{{ first() + 1 }}–{{ first() + rows().length }} of {{ invoices.length }}</span
|
|
1710
|
+
>
|
|
1711
|
+
<nav
|
|
1712
|
+
slPagination
|
|
1713
|
+
[count]="invoices.length"
|
|
1714
|
+
[page]="page()"
|
|
1715
|
+
[pageSize]="pageSize"
|
|
1716
|
+
(pageChange)="page.set($event.value)"
|
|
1717
|
+
>
|
|
1718
|
+
<button slPaginationPrevious type="button"></button>
|
|
1719
|
+
<sl-pagination-items></sl-pagination-items>
|
|
1720
|
+
<button slPaginationNext type="button"></button>
|
|
1721
|
+
</nav>
|
|
1722
|
+
</div>
|
|
1723
|
+
</div>
|
|
1724
|
+
`,
|
|
1725
|
+
})
|
|
1726
|
+
export class TablePagination {
|
|
1727
|
+
readonly invoices = INVOICES;
|
|
1728
|
+
readonly pageSize = PAGE_SIZE;
|
|
1729
|
+
readonly usd = USD;
|
|
1730
|
+
readonly page = signal(1);
|
|
1731
|
+
readonly first = computed(() => (this.page() - 1) * PAGE_SIZE);
|
|
1732
|
+
readonly rows = computed(() => INVOICES.slice(this.first(), this.first() + PAGE_SIZE));
|
|
1733
|
+
}
|
|
1734
|
+
```
|
|
1735
|
+
|
|
1736
|
+
### refreshing.ts
|
|
1737
|
+
|
|
1738
|
+
Example
|
|
1739
|
+
|
|
1740
|
+
```ts
|
|
1741
|
+
import { Component, DestroyRef, inject, signal } from '@angular/core';
|
|
1742
|
+
import { SlButton } from '@slotted/angular/button';
|
|
1743
|
+
import { SlStack } from '@slotted/angular/stack';
|
|
1744
|
+
import {
|
|
1745
|
+
SlTable,
|
|
1746
|
+
SlTableBody,
|
|
1747
|
+
SlTableCell,
|
|
1748
|
+
SlTableColumnHeader,
|
|
1749
|
+
SlTableContent,
|
|
1750
|
+
SlTableHead,
|
|
1751
|
+
SlTableRow,
|
|
1752
|
+
SlTableRowHeader,
|
|
1753
|
+
} from '@slotted/angular/table';
|
|
1754
|
+
|
|
1755
|
+
const USD = new Intl.NumberFormat('en-US', { currency: 'USD', style: 'currency' });
|
|
1756
|
+
|
|
1757
|
+
const PURCHASE_ORDERS = [
|
|
1758
|
+
{ id: 'PO-7710', supplier: 'Exotic Liquids', expected: 'Oct 3', value: 4120 },
|
|
1759
|
+
{ id: 'PO-7711', supplier: 'Tokyo Traders', expected: 'Oct 6', value: 2875.5 },
|
|
1760
|
+
{ id: 'PO-7712', supplier: 'Pavlova, Ltd.', expected: 'Oct 8', value: 9310 },
|
|
1761
|
+
];
|
|
1762
|
+
|
|
1763
|
+
@Component({
|
|
1764
|
+
selector: 'app-table-refreshing',
|
|
1765
|
+
imports: [
|
|
1766
|
+
SlButton,
|
|
1767
|
+
SlStack,
|
|
1768
|
+
SlTable,
|
|
1769
|
+
SlTableBody,
|
|
1770
|
+
SlTableCell,
|
|
1771
|
+
SlTableColumnHeader,
|
|
1772
|
+
SlTableContent,
|
|
1773
|
+
SlTableHead,
|
|
1774
|
+
SlTableRow,
|
|
1775
|
+
SlTableRowHeader,
|
|
1776
|
+
],
|
|
1777
|
+
template: `
|
|
1778
|
+
<div slStack align="start" [gap]="3">
|
|
1779
|
+
<button
|
|
1780
|
+
slButton
|
|
1781
|
+
type="button"
|
|
1782
|
+
size="sm"
|
|
1783
|
+
variant="outline"
|
|
1784
|
+
[loading]="loading()"
|
|
1785
|
+
(click)="refresh()"
|
|
1786
|
+
>
|
|
1787
|
+
Refresh
|
|
1788
|
+
</button>
|
|
1789
|
+
<div slTable [columns]="4" [loading]="loading()">
|
|
1790
|
+
<div slTableContent aria-label="Purchase orders">
|
|
1791
|
+
<thead slTableHead>
|
|
1792
|
+
<tr slTableRow>
|
|
1793
|
+
<th slTableColumnHeader>Purchase order</th>
|
|
1794
|
+
<th slTableColumnHeader>Supplier</th>
|
|
1795
|
+
<th slTableColumnHeader>Expected</th>
|
|
1796
|
+
<th slTableColumnHeader numeric>Value</th>
|
|
1797
|
+
</tr>
|
|
1798
|
+
</thead>
|
|
1799
|
+
<tbody slTableBody>
|
|
1800
|
+
@for (order of orders; track order.id) {
|
|
1801
|
+
<tr slTableRow [value]="order.id">
|
|
1802
|
+
<th slTableRowHeader text="nowrap">{{ order.id }}</th>
|
|
1803
|
+
<td slTableCell>{{ order.supplier }}</td>
|
|
1804
|
+
<td slTableCell>{{ order.expected }}</td>
|
|
1805
|
+
<td slTableCell numeric>{{ usd.format(order.value) }}</td>
|
|
1806
|
+
</tr>
|
|
1807
|
+
}
|
|
1808
|
+
</tbody>
|
|
1809
|
+
</div>
|
|
1810
|
+
</div>
|
|
1811
|
+
</div>
|
|
1812
|
+
`,
|
|
1813
|
+
})
|
|
1814
|
+
export class TableRefreshing {
|
|
1815
|
+
readonly orders = PURCHASE_ORDERS;
|
|
1816
|
+
readonly usd = USD;
|
|
1817
|
+
readonly loading = signal(false);
|
|
1818
|
+
private timer: ReturnType<typeof setTimeout> | undefined;
|
|
1819
|
+
|
|
1820
|
+
constructor() {
|
|
1821
|
+
inject(DestroyRef).onDestroy(() => clearTimeout(this.timer));
|
|
1822
|
+
}
|
|
1823
|
+
|
|
1824
|
+
refresh(): void {
|
|
1825
|
+
this.loading.set(true);
|
|
1826
|
+
clearTimeout(this.timer);
|
|
1827
|
+
this.timer = setTimeout(() => this.loading.set(false), 1500);
|
|
1828
|
+
}
|
|
1829
|
+
}
|
|
1830
|
+
```
|
|
1831
|
+
|
|
1832
|
+
### single-selection.ts
|
|
1833
|
+
|
|
1834
|
+
Example
|
|
1835
|
+
|
|
1836
|
+
```ts
|
|
1837
|
+
import { Component, signal } from '@angular/core';
|
|
1838
|
+
import {
|
|
1839
|
+
SlTable,
|
|
1840
|
+
SlTableBody,
|
|
1841
|
+
SlTableCell,
|
|
1842
|
+
SlTableColumnHeader,
|
|
1843
|
+
SlTableContent,
|
|
1844
|
+
SlTableHead,
|
|
1845
|
+
SlTableRow,
|
|
1846
|
+
SlTableRowHeader,
|
|
1847
|
+
SlTableSelect,
|
|
1848
|
+
} from '@slotted/angular/table';
|
|
1849
|
+
|
|
1850
|
+
const RATES = [
|
|
1851
|
+
{ id: 'ups-ground', carrier: 'UPS Ground', days: '3–5 days', price: '$18.40' },
|
|
1852
|
+
{ id: 'fedex-2day', carrier: 'FedEx 2Day', days: '2 days', price: '$31.15' },
|
|
1853
|
+
{ id: 'usps-priority', carrier: 'USPS Priority', days: '1–3 days', price: '$24.90' },
|
|
1854
|
+
];
|
|
1855
|
+
|
|
1856
|
+
@Component({
|
|
1857
|
+
selector: 'app-table-single-selection',
|
|
1858
|
+
imports: [
|
|
1859
|
+
SlTable,
|
|
1860
|
+
SlTableBody,
|
|
1861
|
+
SlTableCell,
|
|
1862
|
+
SlTableColumnHeader,
|
|
1863
|
+
SlTableContent,
|
|
1864
|
+
SlTableHead,
|
|
1865
|
+
SlTableRow,
|
|
1866
|
+
SlTableRowHeader,
|
|
1867
|
+
SlTableSelect,
|
|
1868
|
+
],
|
|
1869
|
+
template: `
|
|
1870
|
+
<div slTable [columns]="4" selectionMode="single" [(value)]="rate">
|
|
1871
|
+
<div slTableContent aria-label="Shipping rates for SO-10423">
|
|
1872
|
+
<thead slTableHead>
|
|
1873
|
+
<tr slTableRow>
|
|
1874
|
+
<th slTableColumnHeader></th>
|
|
1875
|
+
<th slTableColumnHeader>Carrier</th>
|
|
1876
|
+
<th slTableColumnHeader>Transit</th>
|
|
1877
|
+
<th slTableColumnHeader numeric>Price</th>
|
|
1878
|
+
</tr>
|
|
1879
|
+
</thead>
|
|
1880
|
+
<tbody slTableBody>
|
|
1881
|
+
@for (option of rates; track option.id) {
|
|
1882
|
+
<tr slTableRow [value]="option.id">
|
|
1883
|
+
<td slTableSelect></td>
|
|
1884
|
+
<th slTableRowHeader>{{ option.carrier }}</th>
|
|
1885
|
+
<td slTableCell>{{ option.days }}</td>
|
|
1886
|
+
<td slTableCell numeric>{{ option.price }}</td>
|
|
1887
|
+
</tr>
|
|
1888
|
+
}
|
|
1889
|
+
</tbody>
|
|
1890
|
+
</div>
|
|
1891
|
+
</div>
|
|
1892
|
+
`,
|
|
1893
|
+
})
|
|
1894
|
+
export class TableSingleSelection {
|
|
1895
|
+
readonly rates = RATES;
|
|
1896
|
+
readonly rate = signal<readonly string[]>(['ups-ground']);
|
|
1897
|
+
}
|
|
1898
|
+
```
|
|
1899
|
+
|
|
1900
|
+
### variants.ts
|
|
1901
|
+
|
|
1902
|
+
Example
|
|
1903
|
+
|
|
1904
|
+
```ts
|
|
1905
|
+
import { Component } from '@angular/core';
|
|
1906
|
+
import { SlStack } from '@slotted/angular/stack';
|
|
1907
|
+
import {
|
|
1908
|
+
SlTable,
|
|
1909
|
+
SlTableBody,
|
|
1910
|
+
SlTableCaption,
|
|
1911
|
+
SlTableCell,
|
|
1912
|
+
SlTableColumnHeader,
|
|
1913
|
+
SlTableContent,
|
|
1914
|
+
SlTableHead,
|
|
1915
|
+
SlTableRow,
|
|
1916
|
+
SlTableRowHeader,
|
|
1917
|
+
} from '@slotted/angular/table';
|
|
1918
|
+
|
|
1919
|
+
const SHIPMENTS = [
|
|
1920
|
+
{ id: 'SH-3301', carrier: 'UPS Ground', cartons: 12 },
|
|
1921
|
+
{ id: 'SH-3302', carrier: 'FedEx Express', cartons: 3 },
|
|
1922
|
+
{ id: 'SH-3303', carrier: 'USPS Priority', cartons: 1 },
|
|
1923
|
+
];
|
|
1924
|
+
|
|
1925
|
+
const VARIANTS = [
|
|
1926
|
+
{ variant: 'plain', caption: 'Plain: inside a card that already draws the box' },
|
|
1927
|
+
{ variant: 'ruled', caption: 'Ruled: the default, a rule between rows' },
|
|
1928
|
+
{ variant: 'framed', caption: 'Framed: the table is its own panel' },
|
|
1929
|
+
] as const;
|
|
1930
|
+
|
|
1931
|
+
@Component({
|
|
1932
|
+
selector: 'app-table-variants',
|
|
1933
|
+
imports: [
|
|
1934
|
+
SlStack,
|
|
1935
|
+
SlTable,
|
|
1936
|
+
SlTableBody,
|
|
1937
|
+
SlTableCaption,
|
|
1938
|
+
SlTableCell,
|
|
1939
|
+
SlTableColumnHeader,
|
|
1940
|
+
SlTableContent,
|
|
1941
|
+
SlTableHead,
|
|
1942
|
+
SlTableRow,
|
|
1943
|
+
SlTableRowHeader,
|
|
1944
|
+
],
|
|
1945
|
+
template: `
|
|
1946
|
+
<div slStack [gap]="6">
|
|
1947
|
+
@for (item of variants; track item.variant) {
|
|
1948
|
+
<div slTable [columns]="3" [variant]="item.variant">
|
|
1949
|
+
<div slTableContent>
|
|
1950
|
+
<caption slTableCaption>
|
|
1951
|
+
{{
|
|
1952
|
+
item.caption
|
|
1953
|
+
}}
|
|
1954
|
+
</caption>
|
|
1955
|
+
<thead slTableHead>
|
|
1956
|
+
<tr slTableRow>
|
|
1957
|
+
<th slTableColumnHeader>Shipment</th>
|
|
1958
|
+
<th slTableColumnHeader>Carrier</th>
|
|
1959
|
+
<th slTableColumnHeader numeric>Cartons</th>
|
|
1960
|
+
</tr>
|
|
1961
|
+
</thead>
|
|
1962
|
+
<tbody slTableBody>
|
|
1963
|
+
@for (shipment of shipments; track shipment.id) {
|
|
1964
|
+
<tr slTableRow [value]="shipment.id">
|
|
1965
|
+
<th slTableRowHeader>{{ shipment.id }}</th>
|
|
1966
|
+
<td slTableCell>{{ shipment.carrier }}</td>
|
|
1967
|
+
<td slTableCell numeric>{{ shipment.cartons }}</td>
|
|
1968
|
+
</tr>
|
|
1969
|
+
}
|
|
1970
|
+
</tbody>
|
|
1971
|
+
</div>
|
|
1972
|
+
</div>
|
|
1973
|
+
}
|
|
1974
|
+
</div>
|
|
1975
|
+
`,
|
|
1976
|
+
})
|
|
1977
|
+
export class TableVariants {
|
|
1978
|
+
readonly shipments = SHIPMENTS;
|
|
1979
|
+
readonly variants = VARIANTS;
|
|
1980
|
+
}
|
|
1981
|
+
```
|