bitboss-ui 2.1.113 → 2.1.115
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/dist/ai/BaseButton.md +448 -0
- package/dist/ai/BaseCheckbox.md +494 -0
- package/dist/ai/BaseCheckboxGroup.md +597 -0
- package/dist/ai/BaseColorInput.md +461 -0
- package/dist/ai/BaseDatePicker.md +739 -0
- package/dist/ai/BaseDatePickerInput.md +1517 -0
- package/dist/ai/BaseDialog.md +610 -0
- package/dist/ai/BaseInputContainer.md +570 -0
- package/dist/ai/BaseNumberInput.md +509 -0
- package/dist/ai/BaseRadio.md +405 -0
- package/dist/ai/BaseRadioGroup.md +535 -0
- package/dist/ai/BaseRating.md +489 -0
- package/dist/ai/BaseSelect.md +1720 -0
- package/dist/ai/BaseSlider.md +871 -0
- package/dist/ai/BaseSwitch.md +322 -0
- package/dist/ai/BaseSwitchGroup.md +298 -0
- package/dist/ai/BaseTag.md +624 -0
- package/dist/ai/BaseTextInput.md +392 -0
- package/dist/ai/BaseTextarea.md +398 -0
- package/dist/ai/BbAccordion.md +135 -0
- package/dist/ai/BbAlert.md +226 -0
- package/dist/ai/BbAvatar.md +200 -0
- package/dist/ai/BbBadge.md +185 -0
- package/dist/ai/BbBreadcrumbs.md +536 -0
- package/dist/ai/BbButton.md +687 -0
- package/dist/ai/BbCheckbox.md +280 -0
- package/dist/ai/BbCheckboxGroup.md +387 -0
- package/dist/ai/BbChip.md +148 -0
- package/dist/ai/BbCollapsible.md +119 -0
- package/dist/ai/BbColorInput.md +345 -0
- package/dist/ai/BbColorPalette.md +360 -0
- package/dist/ai/BbConfirm.md +160 -0
- package/dist/ai/BbDatePickerInput.md +414 -0
- package/dist/ai/BbDialog.md +135 -0
- package/dist/ai/BbDropdown.md +765 -0
- package/dist/ai/BbDropdownButton.md +629 -0
- package/dist/ai/BbDropzone.md +504 -0
- package/dist/ai/BbIcon.md +238 -0
- package/dist/ai/BbIntersection.md +121 -0
- package/dist/ai/BbNumberInput.md +372 -0
- package/dist/ai/BbOffCanvas.md +549 -0
- package/dist/ai/BbPagination.md +562 -0
- package/dist/ai/BbPopover.md +580 -0
- package/dist/ai/BbProgress.md +97 -0
- package/dist/ai/BbRadio.md +256 -0
- package/dist/ai/BbRadioGroup.md +373 -0
- package/dist/ai/BbRating.md +245 -0
- package/dist/ai/BbRatio.md +62 -0
- package/dist/ai/BbRows.md +307 -0
- package/dist/ai/BbSelect.md +562 -0
- package/dist/ai/BbSelectPopover.md +2010 -0
- package/dist/ai/BbSlider.md +274 -0
- package/dist/ai/BbSmoothHeight.md +167 -0
- package/dist/ai/BbSpinner.md +154 -0
- package/dist/ai/BbSwitch.md +151 -0
- package/dist/ai/BbSwitchGroup.md +237 -0
- package/dist/ai/BbTab.md +954 -0
- package/dist/ai/BbTable.md +1624 -0
- package/dist/ai/BbTag.md +315 -0
- package/dist/ai/BbTextInput.md +357 -0
- package/dist/ai/BbTextarea.md +277 -0
- package/dist/ai/BbToast.md +219 -0
- package/dist/ai/BbTooltip.md +353 -0
- package/dist/ai/BbTree.md +271 -0
- package/dist/ai/ChipsBox.md +211 -0
- package/dist/ai/ClearableButton.md +67 -0
- package/dist/ai/CommaBox.md +212 -0
- package/dist/ai/CommonInputInnerContainer.md +419 -0
- package/dist/ai/CommonInputOuterContainer.md +56 -0
- package/dist/ai/CommonPopover.md +446 -0
- package/dist/ai/ErrorIcon.md +61 -0
- package/dist/ai/FlatListBox.md +382 -0
- package/dist/ai/GroupedListBox.md +538 -0
- package/dist/ai/ListBox.md +234 -0
- package/dist/ai/OptionsContainer.md +257 -0
- package/dist/ai/index.md +124 -0
- package/dist/components/BaseButton/BaseButton.vue.d.ts +2 -163
- package/dist/components/BaseButton/types.d.ts +158 -0
- package/dist/components/BaseCheckbox/BaseCheckbox.vue.d.ts +4 -4
- package/dist/components/BaseCheckboxGroup/BaseCheckboxGroup.vue.d.ts +2 -2
- package/dist/components/BaseCheckboxGroup/types.d.ts +16 -9
- package/dist/components/BaseColorInput/BaseColorInput.vue.d.ts +12 -52
- package/dist/components/BaseDatePicker/BaseDatePicker.vue.d.ts +4 -76
- package/dist/components/BaseDatePicker/types.d.ts +100 -0
- package/dist/components/BaseDatePickerInput/BaseDatePickerInput.vue.d.ts +18 -315
- package/dist/components/BaseDatePickerInput/types.d.ts +206 -0
- package/dist/components/BaseDialog/BaseDialog.vue.d.ts +6 -156
- package/dist/components/BaseDialog/types.d.ts +180 -0
- package/dist/components/BaseInputContainer/BaseInputContainer.vue.d.ts +1 -107
- package/dist/components/BaseInputContainer/types.d.ts +126 -0
- package/dist/components/BaseNumberInput/BaseNumberInput.vue.d.ts +7 -170
- package/dist/components/BaseNumberInput/types.d.ts +191 -0
- package/dist/components/BaseRadio/BaseRadio.vue.d.ts +6 -119
- package/dist/components/BaseRadio/types.d.ts +173 -0
- package/dist/components/BaseRadioGroup/BaseRadioGroup.vue.d.ts +4 -274
- package/dist/components/BaseRadioGroup/types.d.ts +240 -0
- package/dist/components/BaseRating/BaseRating.vue.d.ts +5 -106
- package/dist/components/BaseRating/types.d.ts +144 -0
- package/dist/components/BaseSelect/BaseSelect.vue.d.ts +2 -363
- package/dist/components/BaseSelect/types.d.ts +457 -0
- package/dist/components/BaseSlider/BaseSlider.vue.d.ts +6 -178
- package/dist/components/BaseSlider/types.d.ts +201 -0
- package/dist/components/BaseSwitch/BaseSwitch.vue.d.ts +7 -35
- package/dist/components/BaseSwitch/types.d.ts +25 -0
- package/dist/components/BaseSwitchGroup/BaseSwitchGroup.vue.d.ts +5 -11
- package/dist/components/BaseSwitchGroup/types.d.ts +8 -0
- package/dist/components/BaseTag/BaseTag.vue.d.ts +27 -222
- package/dist/components/BaseTag/types.d.ts +136 -0
- package/dist/components/BaseTextInput/BaseTextInput.vue.d.ts +5 -141
- package/dist/components/BaseTextInput/types.d.ts +166 -0
- package/dist/components/BaseTextarea/BaseTextarea.vue.d.ts +5 -131
- package/dist/components/BaseTextarea/types.d.ts +151 -0
- package/dist/components/BbAccordion/BbAccordion.vue.d.ts +3 -51
- package/dist/components/BbAccordion/types.d.ts +32 -0
- package/dist/components/BbAlert/BbAlert.vue.d.ts +3 -50
- package/dist/components/BbAlert/types.d.ts +42 -0
- package/dist/components/BbAvatar/BbAvatar.vue.d.ts +3 -23
- package/dist/components/BbAvatar/types.d.ts +34 -0
- package/dist/components/BbBadge/BbBadge.vue.d.ts +3 -40
- package/dist/components/BbBadge/types.d.ts +30 -0
- package/dist/components/BbBreadcrumbs/BbBreadcrumbs.vue.d.ts +14 -178
- package/dist/components/BbBreadcrumbs/types.d.ts +109 -0
- package/dist/components/BbButton/BbButton.vue.d.ts +4 -163
- package/dist/components/BbButton/types.d.ts +159 -0
- package/dist/components/BbCheckbox/BbCheckbox.vue.d.ts +7 -165
- package/dist/components/BbCheckbox/types.d.ts +130 -0
- package/dist/components/BbCheckboxGroup/BbCheckboxGroup.vue.d.ts +7 -324
- package/dist/components/BbCheckboxGroup/types.d.ts +189 -0
- package/dist/components/BbChip/BbChip.vue.d.ts +6 -28
- package/dist/components/BbChip/types.d.ts +23 -0
- package/dist/components/BbCollapsible/BbCollapsible.vue.d.ts +3 -24
- package/dist/components/BbCollapsible/types.d.ts +20 -0
- package/dist/components/BbColorInput/BbColorInput.vue.d.ts +10 -151
- package/dist/components/BbColorInput/types.d.ts +131 -0
- package/dist/components/BbColorPalette/BbColorPalette.vue.d.ts +2 -112
- package/dist/components/BbColorPalette/types.d.ts +127 -0
- package/dist/components/BbDatePickerInput/BbDatePickerInput.vue.d.ts +6 -212
- package/dist/components/BbDatePickerInput/types.d.ts +180 -0
- package/dist/components/BbDialog/BbDialog.vue.d.ts +2 -2
- package/dist/components/BbDialog/types.d.ts +1 -0
- package/dist/components/BbDropdown/BbDropdown.vue.d.ts +21 -247
- package/dist/components/BbDropdown/types.d.ts +147 -0
- package/dist/components/BbDropdownButton/BbDropdownButton.vue.d.ts +16 -209
- package/dist/components/BbDropdownButton/types.d.ts +114 -0
- package/dist/components/BbDropzone/BbDropzone.vue.d.ts +7 -86
- package/dist/components/BbDropzone/types.d.ts +67 -0
- package/dist/components/BbIcon/BbIcon.vue.d.ts +2 -26
- package/dist/components/BbIcon/types.d.ts +28 -0
- package/dist/components/BbIntersection/BbIntersection.vue.d.ts +3 -41
- package/dist/components/BbIntersection/types.d.ts +36 -0
- package/dist/components/BbNumberInput/BbNumberInput.vue.d.ts +44 -175
- package/dist/components/BbNumberInput/types.d.ts +130 -0
- package/dist/components/BbOffCanvas/BbOffCanvas.vue.d.ts +5 -93
- package/dist/components/BbOffCanvas/types.d.ts +97 -0
- package/dist/components/BbPagination/BbPagination.vue.d.ts +4 -87
- package/dist/components/BbPagination/types.d.ts +80 -0
- package/dist/components/BbPopover/BbPopover.vue.d.ts +9 -135
- package/dist/components/BbPopover/types.d.ts +99 -0
- package/dist/components/BbProgress/BbProgress.vue.d.ts +2 -14
- package/dist/components/BbProgress/types.d.ts +20 -0
- package/dist/components/BbRadio/BbRadio.vue.d.ts +7 -150
- package/dist/components/BbRadio/types.d.ts +117 -0
- package/dist/components/BbRadioGroup/BbRadioGroup.vue.d.ts +7 -322
- package/dist/components/BbRadioGroup/types.d.ts +182 -0
- package/dist/components/BbRating/BbRating.vue.d.ts +10 -113
- package/dist/components/BbRating/types.d.ts +105 -0
- package/dist/components/BbRatio/BbRatio.vue.d.ts +3 -18
- package/dist/components/BbRatio/types.d.ts +15 -0
- package/dist/components/BbSelect/BbSelect.vue.d.ts +7 -375
- package/dist/components/BbSelect/types.d.ts +351 -0
- package/dist/components/BbSelectPopover/BbSelectPopover.vue.d.ts +1 -1
- package/dist/components/BbSelectPopover/types.d.ts +351 -0
- package/dist/components/BbSlider/BbSlider.vue.d.ts +10 -129
- package/dist/components/BbSlider/types.d.ts +123 -0
- package/dist/components/BbSmoothHeight/BbSmoothHeight.vue.d.ts +2 -23
- package/dist/components/BbSmoothHeight/types.d.ts +24 -0
- package/dist/components/BbSpinner/BbSpinner.vue.d.ts +3 -5
- package/dist/components/BbSpinner/types.d.ts +8 -0
- package/dist/components/BbSwitch/BbSwitch.vue.d.ts +9 -65
- package/dist/components/BbSwitch/types.d.ts +29 -0
- package/dist/components/BbSwitchGroup/BbSwitchGroup.vue.d.ts +7 -190
- package/dist/components/BbSwitchGroup/types.d.ts +81 -0
- package/dist/components/BbTab/BbTab.vue.d.ts +9 -247
- package/dist/components/BbTab/types.d.ts +186 -0
- package/dist/components/BbTag/BbTag.vue.d.ts +6 -156
- package/dist/components/BbTag/types.d.ts +158 -0
- package/dist/components/BbTextInput/BbTextInput.vue.d.ts +10 -152
- package/dist/components/BbTextInput/types.d.ts +137 -0
- package/dist/components/BbTextarea/BbTextarea.vue.d.ts +10 -142
- package/dist/components/BbTextarea/types.d.ts +123 -0
- package/dist/components/BbToast/BbToast.vue.d.ts +2 -6
- package/dist/components/BbToast/types.d.ts +8 -0
- package/dist/components/BbTooltip/BbTooltip.vue.d.ts +8 -65
- package/dist/components/BbTooltip/types.d.ts +55 -0
- package/dist/components/BbTree/BbTree.vue.d.ts +2 -65
- package/dist/components/BbTree/types.d.ts +69 -0
- package/dist/components/{ChipsBox.vue.d.ts → ChipsBox/ChipsBox.vue.d.ts} +5 -6
- package/dist/components/ChipsBox/types.d.ts +14 -0
- package/dist/components/{ClearableButton.vue.d.ts → ClearableButton/ClearableButton.vue.d.ts} +2 -0
- package/dist/components/ClearableButton/types.d.ts +3 -0
- package/dist/components/{CommaBox.vue.d.ts → CommaBox/CommaBox.vue.d.ts} +5 -6
- package/dist/components/CommaBox/types.d.ts +14 -0
- package/dist/components/CommonInputInnerContainer/CommonInputInnerContainer.vue.d.ts +25 -0
- package/dist/components/CommonInputInnerContainer/types.d.ts +47 -0
- package/dist/components/CommonInputOuterContainer/CommonInputOuterContainer.vue.d.ts +17 -0
- package/dist/components/CommonInputOuterContainer/types.d.ts +16 -0
- package/dist/components/{CommonPopover.vue.d.ts → CommonPopover/CommonPopover.vue.d.ts} +5 -30
- package/dist/components/CommonPopover/types.d.ts +43 -0
- package/dist/components/{ErrorIcon.vue.d.ts → ErrorIcon/ErrorIcon.vue.d.ts} +2 -0
- package/dist/components/ErrorIcon/types.d.ts +3 -0
- package/dist/components/FlatListBox/types.d.ts +97 -0
- package/dist/components/GroupedListBox/types.d.ts +118 -0
- package/dist/components/ListBox/ListBox.vue.d.ts +30 -0
- package/dist/components/ListBox/types.d.ts +133 -0
- package/dist/components/OptionsContainer/OptionsContainer.vue.d.ts +13 -0
- package/dist/components/OptionsContainer/types.d.ts +96 -0
- package/dist/composables/useBbConfig.d.ts +1 -1
- package/dist/composables/useConfirm.d.ts +1 -1
- package/dist/index.css +1 -1
- package/dist/index.d.ts +18 -18
- package/dist/index109.js +9 -9
- package/dist/index110.js +50 -49
- package/dist/index114.js +1 -1
- package/dist/index118.js +1 -1
- package/dist/index122.js +1 -0
- package/dist/index124.js +4 -4
- package/dist/index126.js +13 -13
- package/dist/index132.js +22 -19
- package/dist/index134.js +1 -1
- package/dist/index136.js +5 -5
- package/dist/index138.js +1 -1
- package/dist/index14.js +1 -1
- package/dist/index140.js +18 -17
- package/dist/index144.js +1 -1
- package/dist/index146.js +2 -2
- package/dist/index149.js +2 -2
- package/dist/index16.js +3 -3
- package/dist/index18.js +3 -3
- package/dist/index20.js +70 -59
- package/dist/index22.js +14 -14
- package/dist/index221.js +138 -2
- package/dist/index222.js +2 -138
- package/dist/index224.js +5 -34
- package/dist/index225.js +7 -32
- package/dist/index226.js +32 -26
- package/dist/index227.js +7 -0
- package/dist/index228.js +5 -5
- package/dist/index229.js +5 -8
- package/dist/index230.js +5 -7
- package/dist/index231.js +3 -2
- package/dist/index232.js +2 -9
- package/dist/index233.js +6 -13
- package/dist/index234.js +8 -3
- package/dist/index235.js +268 -2
- package/dist/index236.js +52 -11
- package/dist/index237.js +50 -6
- package/dist/index238.js +32 -3
- package/dist/index239.js +60 -3
- package/dist/index24.js +10 -10
- package/dist/index240.js +13 -2
- package/dist/index241.js +187 -17
- package/dist/index242.js +3 -12
- package/dist/index243.js +2 -51
- package/dist/index244.js +2 -18
- package/dist/index245.js +2 -12
- package/dist/index246.js +12 -16
- package/dist/index247.js +11 -28
- package/dist/index248.js +48 -15
- package/dist/index249.js +17 -4
- package/dist/index250.js +2 -2
- package/dist/index252.js +2 -2
- package/dist/index254.js +3 -135
- package/dist/index255.js +4 -0
- package/dist/index256.js +4 -107
- package/dist/index257.js +19 -12
- package/dist/index258.js +6 -2
- package/dist/index259.js +16 -7
- package/dist/index26.js +3 -3
- package/dist/index260.js +86 -7
- package/dist/index262.js +32 -0
- package/dist/index263.js +18 -5
- package/dist/index264.js +12 -5
- package/dist/index265.js +18 -5
- package/dist/index266.js +2 -5
- package/dist/index267.js +7 -5
- package/dist/index268.js +7 -5
- package/dist/index269.js +3 -67
- package/dist/index270.js +4 -33
- package/dist/index271.js +5 -2
- package/dist/index272.js +5 -2
- package/dist/index273.js +5 -3
- package/dist/index274.js +135 -4
- package/dist/index276.js +9 -6
- package/dist/index277.js +7 -11
- package/dist/index278.js +23 -5
- package/dist/index279.js +3 -5
- package/dist/index28.js +57 -55
- package/dist/index280.js +21 -266
- package/dist/index281.js +364 -43
- package/dist/index283.js +32 -31
- package/dist/index284.js +3 -60
- package/dist/index285.js +25 -4
- package/dist/index286.js +3 -20
- package/dist/index287.js +18 -5
- package/dist/index288.js +12 -373
- package/dist/index289.js +109 -0
- package/dist/index290.js +11 -6
- package/dist/index291.js +66 -15
- package/dist/index292.js +32 -10
- package/dist/index294.js +5 -8
- package/dist/index295.js +9 -20
- package/dist/index296.js +2 -8
- package/dist/index297.js +9 -23
- package/dist/index298.js +52 -24
- package/dist/index299.js +5 -188
- package/dist/index30.js +3 -3
- package/dist/index300.js +21 -3
- package/dist/index301.js +28 -3
- package/dist/index303.js +9 -0
- package/dist/index304.js +2 -7
- package/dist/index305.js +280 -3
- package/dist/index306.js +2 -2
- package/dist/index307.js +16 -5
- package/dist/index308.js +2 -7
- package/dist/index309.js +16 -3
- package/dist/index310.js +2 -3
- package/dist/index311.js +27 -3
- package/dist/index312.js +2 -2
- package/dist/index313.js +2 -28
- package/dist/index314.js +2 -17
- package/dist/index315.js +2 -4
- package/dist/index316.js +1 -1
- package/dist/index317.js +28 -3
- package/dist/index318.js +2 -280
- package/dist/index319.js +7 -2
- package/dist/index32.js +2 -2
- package/dist/index320.js +719 -125
- package/dist/index321.js +366 -2
- package/dist/index322.js +56 -14
- package/dist/index323.js +4 -2
- package/dist/index324.js +3 -16
- package/dist/index325.js +17 -2
- package/dist/index326.js +3 -16
- package/dist/index327.js +3 -2
- package/dist/index328.js +3 -19
- package/dist/index329.js +3 -2
- package/dist/index330.js +120 -22
- package/dist/index331.js +2 -2
- package/dist/index332.js +15 -2
- package/dist/index333.js +2 -2
- package/dist/index334.js +19 -2
- package/dist/index335.js +2 -2
- package/dist/index336.js +5 -2
- package/dist/index337.js +5 -3
- package/dist/index338.js +2 -4
- package/dist/index339.js +4 -719
- package/dist/index34.js +8 -8
- package/dist/index340.js +2 -366
- package/dist/index341.js +3 -57
- package/dist/index342.js +3 -6
- package/dist/index343.js +6 -5
- package/dist/index344.js +6 -34
- package/dist/index345.js +17 -127
- package/dist/index346.js +7 -396
- package/dist/index347.js +14 -199
- package/dist/index348.js +5 -259
- package/dist/index349.js +6 -227
- package/dist/index352.js +35 -2
- package/dist/index353.js +129 -2
- package/dist/index354.js +378 -114
- package/dist/index355.js +92 -6
- package/dist/index356.js +226 -17
- package/dist/index357.js +22 -9
- package/dist/index359.js +7 -5
- package/dist/index36.js +4 -4
- package/dist/index360.js +200 -7
- package/dist/index361.js +255 -18
- package/dist/index362.js +136 -0
- package/dist/index363.js +2 -93
- package/dist/index364.js +2 -441
- package/dist/index365.js +427 -114
- package/dist/index366.js +127 -46
- package/dist/index367.js +44 -67
- package/dist/index368.js +66 -516
- package/dist/index369.js +515 -45
- package/dist/index370.js +52 -0
- package/dist/index38.js +133 -131
- package/dist/index40.js +8 -8
- package/dist/index42.js +2 -2
- package/dist/index44.js +16 -15
- package/dist/index46.js +4 -4
- package/dist/index50.js +28 -25
- package/dist/index54.js +1 -1
- package/dist/index56.js +1 -1
- package/dist/index58.js +2 -2
- package/dist/index60.js +2 -2
- package/dist/index62.js +5 -5
- package/dist/index66.js +3 -1
- package/dist/index68.js +1 -1
- package/dist/index74.js +4 -4
- package/dist/index82.js +6 -6
- package/dist/index84.js +1 -1
- package/dist/index86.js +2 -2
- package/dist/index88.js +3 -3
- package/dist/index90.js +1 -1
- package/dist/index93.js +3 -3
- package/dist/index95.js +2 -2
- package/dist/index97.js +5 -5
- package/dist/index99.js +1 -1
- package/dist/utilities/functions/parseSize.d.ts +1 -1
- package/package.json +5 -3
- package/dist/components/CommonInputInnerContainer.vue.d.ts +0 -81
- package/dist/components/CommonInputOuterContainer.vue.d.ts +0 -41
- package/dist/components/FlatListBox.vue.d.ts +0 -119
- package/dist/components/GroupedListBox.vue.d.ts +0 -153
- package/dist/components/ListBox.vue.d.ts +0 -170
- package/dist/components/OptionsContainer.vue.d.ts +0 -172
- package/dist/index261.js +0 -88
- package/dist/index275.js +0 -25
- package/dist/index282.js +0 -54
- package/dist/index293.js +0 -5
- package/dist/index302.js +0 -55
- package/dist/index358.js +0 -17
|
@@ -0,0 +1,1624 @@
|
|
|
1
|
+
# BbTable
|
|
2
|
+
|
|
3
|
+
## Template & Script
|
|
4
|
+
|
|
5
|
+
```vue
|
|
6
|
+
<template>
|
|
7
|
+
<component
|
|
8
|
+
:is="containerTag"
|
|
9
|
+
:aria-busy="loading"
|
|
10
|
+
:aria-rowcount="hasProvidedAccessibilityData ? props.totalItems : undefined"
|
|
11
|
+
:class="containerClass"
|
|
12
|
+
:inert="disabled"
|
|
13
|
+
>
|
|
14
|
+
<legend v-if="selectable" class="sr-only">{{ legend }}</legend>
|
|
15
|
+
<table ref="tableRef">
|
|
16
|
+
<caption
|
|
17
|
+
v-if="caption"
|
|
18
|
+
:class="{
|
|
19
|
+
'bb-table-caption': true,
|
|
20
|
+
'sr-only': !displayCaption,
|
|
21
|
+
}"
|
|
22
|
+
>
|
|
23
|
+
{{
|
|
24
|
+
caption
|
|
25
|
+
}}
|
|
26
|
+
</caption>
|
|
27
|
+
<thead>
|
|
28
|
+
<!-- @vue-ignore -->
|
|
29
|
+
<slot name="thead">
|
|
30
|
+
<tr
|
|
31
|
+
:aria-rowindex="hasProvidedAccessibilityData ? 1 : undefined"
|
|
32
|
+
class="bb-table-header-row"
|
|
33
|
+
>
|
|
34
|
+
<th
|
|
35
|
+
v-if="selectable"
|
|
36
|
+
class="bb-table-header bb-table-header--select"
|
|
37
|
+
:class="thClass"
|
|
38
|
+
scope="col"
|
|
39
|
+
>
|
|
40
|
+
<!-- @vue-ignore -->
|
|
41
|
+
<slot
|
|
42
|
+
:multiple="multiple"
|
|
43
|
+
:name="'header:select'"
|
|
44
|
+
:select-all="!!selectAll"
|
|
45
|
+
:text="selectText || t('table.selectText').value"
|
|
46
|
+
>
|
|
47
|
+
<span class="bb-table-header__content">
|
|
48
|
+
<label
|
|
49
|
+
v-if="allowSelectAll && multiple"
|
|
50
|
+
class="bb-table-check__label"
|
|
51
|
+
:class="{
|
|
52
|
+
'bb-table-check__label--disabled': disabled,
|
|
53
|
+
}"
|
|
54
|
+
>
|
|
55
|
+
<BaseCheckbox
|
|
56
|
+
:key="indeterminate.toString()"
|
|
57
|
+
v-model="selectAll"
|
|
58
|
+
class="bb-table-check"
|
|
59
|
+
:disabled="disabled"
|
|
60
|
+
:indeterminate="indeterminate"
|
|
61
|
+
:name="`select_all_${name || ''}`"
|
|
62
|
+
:readonly="readonly"
|
|
63
|
+
/>
|
|
64
|
+
<span class="bb-table-check__label-text sr-only"
|
|
65
|
+
>{{ selectAllLabel || t('table.selectAllLabel').value }}
|
|
66
|
+
</span>
|
|
67
|
+
</label>
|
|
68
|
+
<span
|
|
69
|
+
v-else-if="!multiple"
|
|
70
|
+
class="bb-table-radio__label-text sr-only"
|
|
71
|
+
>{{ selectText || t('table.selectText').value }}</span
|
|
72
|
+
>
|
|
73
|
+
</span>
|
|
74
|
+
</slot>
|
|
75
|
+
</th>
|
|
76
|
+
<th
|
|
77
|
+
v-for="header in mappedHeaders"
|
|
78
|
+
:key="header.key"
|
|
79
|
+
:aria-sort="header.sortDirection"
|
|
80
|
+
class="bb-table-header"
|
|
81
|
+
:class="header.classes"
|
|
82
|
+
scope="col"
|
|
83
|
+
>
|
|
84
|
+
<!-- @vue-ignore -->
|
|
85
|
+
<slot
|
|
86
|
+
:classes="header.classes"
|
|
87
|
+
:items="internalItems"
|
|
88
|
+
:label="header.label"
|
|
89
|
+
:name="header.slotName"
|
|
90
|
+
><span class="bb-table-header__content">{{
|
|
91
|
+
header.label
|
|
92
|
+
}}</span></slot
|
|
93
|
+
>
|
|
94
|
+
</th>
|
|
95
|
+
<th
|
|
96
|
+
v-if="actions"
|
|
97
|
+
class="bb-table-header bb-table-header--actions"
|
|
98
|
+
:class="thClass"
|
|
99
|
+
scope="col"
|
|
100
|
+
>
|
|
101
|
+
<!-- @vue-ignore -->
|
|
102
|
+
<slot name="header:actions" :text="actionsText">
|
|
103
|
+
<span class="bb-table-header__content sr-only">
|
|
104
|
+
{{ actionsText }}
|
|
105
|
+
</span>
|
|
106
|
+
</slot>
|
|
107
|
+
</th>
|
|
108
|
+
</tr>
|
|
109
|
+
</slot>
|
|
110
|
+
</thead>
|
|
111
|
+
<tbody>
|
|
112
|
+
<slot v-if="loading" :items="internalItems" name="loading">
|
|
113
|
+
<template v-for="(_, rowIndex) in skeletonLength" :key="rowIndex">
|
|
114
|
+
<tr
|
|
115
|
+
:aria-rowindex="
|
|
116
|
+
hasProvidedAccessibilityData ? rowIndex + 2 : undefined
|
|
117
|
+
"
|
|
118
|
+
class="bb-table-skeleton__row"
|
|
119
|
+
>
|
|
120
|
+
<td
|
|
121
|
+
v-if="selectable"
|
|
122
|
+
class="bb-table-skeleton__cell bb-table-skeleton__cell--select"
|
|
123
|
+
>
|
|
124
|
+
<div class="bb-table-skeleton__placeholder" />
|
|
125
|
+
</td>
|
|
126
|
+
<td
|
|
127
|
+
v-for="(col, colIndex) in props.columns"
|
|
128
|
+
:key="col.key"
|
|
129
|
+
:class="[
|
|
130
|
+
'bb-table-skeleton__cell',
|
|
131
|
+
`bb-table-skeleton__cell--${col.skeleton ?? 'text'}`,
|
|
132
|
+
]"
|
|
133
|
+
>
|
|
134
|
+
<!-- text: 2 lines with dynamic widths -->
|
|
135
|
+
<template v-if="!col.skeleton || col.skeleton === 'text'">
|
|
136
|
+
<div class="bb-table-skeleton__cell-content">
|
|
137
|
+
<div
|
|
138
|
+
class="bb-table-skeleton__line"
|
|
139
|
+
:style="{
|
|
140
|
+
width: `${skeletonLineWidths[(rowIndex + colIndex) % 4]}%`,
|
|
141
|
+
}"
|
|
142
|
+
/>
|
|
143
|
+
<div
|
|
144
|
+
class="bb-table-skeleton__line"
|
|
145
|
+
:style="{
|
|
146
|
+
width: `${skeletonLineWidths[(rowIndex + colIndex + 2) % 4]}%`,
|
|
147
|
+
}"
|
|
148
|
+
/>
|
|
149
|
+
</div>
|
|
150
|
+
</template>
|
|
151
|
+
<!-- avatar: circle only -->
|
|
152
|
+
<div
|
|
153
|
+
v-else-if="col.skeleton === 'avatar'"
|
|
154
|
+
class="bb-table-skeleton__avatar"
|
|
155
|
+
/>
|
|
156
|
+
<!-- avatar-text: avatar + 2 lines -->
|
|
157
|
+
<div
|
|
158
|
+
v-else-if="col.skeleton === 'avatar-text'"
|
|
159
|
+
class="bb-table-skeleton__avatar-text"
|
|
160
|
+
>
|
|
161
|
+
<div class="bb-table-skeleton__avatar" />
|
|
162
|
+
<div class="bb-table-skeleton__cell-content">
|
|
163
|
+
<div
|
|
164
|
+
class="bb-table-skeleton__line"
|
|
165
|
+
:style="{
|
|
166
|
+
width: `${skeletonLineWidths[(rowIndex + colIndex) % 4]}%`,
|
|
167
|
+
}"
|
|
168
|
+
/>
|
|
169
|
+
<div
|
|
170
|
+
class="bb-table-skeleton__line"
|
|
171
|
+
:style="{
|
|
172
|
+
width: `${skeletonLineWidths[(rowIndex + colIndex + 2) % 4]}%`,
|
|
173
|
+
}"
|
|
174
|
+
/>
|
|
175
|
+
</div>
|
|
176
|
+
</div>
|
|
177
|
+
<!-- image: rounded rect -->
|
|
178
|
+
<div
|
|
179
|
+
v-else-if="col.skeleton === 'image'"
|
|
180
|
+
class="bb-table-skeleton__image"
|
|
181
|
+
/>
|
|
182
|
+
<!-- badge: small pill -->
|
|
183
|
+
<div
|
|
184
|
+
v-else-if="col.skeleton === 'badge'"
|
|
185
|
+
class="bb-table-skeleton__badge"
|
|
186
|
+
/>
|
|
187
|
+
</td>
|
|
188
|
+
<td
|
|
189
|
+
v-if="actions"
|
|
190
|
+
class="bb-table-skeleton__cell bb-table-skeleton__cell--actions"
|
|
191
|
+
>
|
|
192
|
+
<div class="bb-table-skeleton__placeholder" />
|
|
193
|
+
</td>
|
|
194
|
+
</tr>
|
|
195
|
+
</template>
|
|
196
|
+
<tr
|
|
197
|
+
:aria-rowindex="
|
|
198
|
+
hasProvidedAccessibilityData ? skeletonLength + 2 : undefined
|
|
199
|
+
"
|
|
200
|
+
class="bb-table-loading__row bb-table-loading__row--sr-only"
|
|
201
|
+
>
|
|
202
|
+
<td
|
|
203
|
+
:colspan="replacementContentSpan"
|
|
204
|
+
class="bb-table-loading__cell"
|
|
205
|
+
aria-live="polite"
|
|
206
|
+
role="status"
|
|
207
|
+
>
|
|
208
|
+
<span class="bb-table-loading__text sr-only">{{
|
|
209
|
+
loadingText
|
|
210
|
+
}}</span>
|
|
211
|
+
</td>
|
|
212
|
+
</tr>
|
|
213
|
+
</slot>
|
|
214
|
+
<slot v-else-if="!options.length" :name="'no-data'">
|
|
215
|
+
<tr
|
|
216
|
+
:aria-rowindex="hasProvidedAccessibilityData ? 2 : undefined"
|
|
217
|
+
class="bb-table-no-data__row"
|
|
218
|
+
>
|
|
219
|
+
<td
|
|
220
|
+
class="bb-table-no-data__cell"
|
|
221
|
+
:colspan="replacementContentSpan"
|
|
222
|
+
>
|
|
223
|
+
<span class="bb-table-no-data__text">{{
|
|
224
|
+
noDataText || t('table.noDataText').value
|
|
225
|
+
}}</span>
|
|
226
|
+
</td>
|
|
227
|
+
</tr>
|
|
228
|
+
</slot>
|
|
229
|
+
<slot v-else name="tbody">
|
|
230
|
+
<template v-for="item in mappedItems" :key="item.valueHash">
|
|
231
|
+
<tr
|
|
232
|
+
:aria-rowindex="
|
|
233
|
+
hasProvidedAccessibilityData && item.rowIndex
|
|
234
|
+
? item.rowIndex
|
|
235
|
+
: undefined
|
|
236
|
+
"
|
|
237
|
+
class="bb-table-data__row"
|
|
238
|
+
@click="item.onRowClick"
|
|
239
|
+
@contextmenu="item.onRowContextMenu"
|
|
240
|
+
@dblclick="item.onRowDblClick"
|
|
241
|
+
>
|
|
242
|
+
<td
|
|
243
|
+
v-if="selectable"
|
|
244
|
+
class="bb-table-data__cell bb-table-data__cell--select"
|
|
245
|
+
:class="tdClass"
|
|
246
|
+
>
|
|
247
|
+
<!-- @vue-ignore -->
|
|
248
|
+
<slot
|
|
249
|
+
:checked="isSelected(item)"
|
|
250
|
+
:disabled="!!item.disabled"
|
|
251
|
+
:input-name="randomName"
|
|
252
|
+
:item="item.item"
|
|
253
|
+
:name="'select'"
|
|
254
|
+
:readonly="!!readonly"
|
|
255
|
+
:value="item.value"
|
|
256
|
+
>
|
|
257
|
+
<!-- We use temp names for these inputs because we don't submit them -->
|
|
258
|
+
<label
|
|
259
|
+
v-if="multiple"
|
|
260
|
+
class="bb-table-check__label"
|
|
261
|
+
:class="{
|
|
262
|
+
'bb-table-check__label--disabled': item.disabled,
|
|
263
|
+
}"
|
|
264
|
+
>
|
|
265
|
+
<BaseCheckbox
|
|
266
|
+
:checked="isSelected(item)"
|
|
267
|
+
class="bb-table-check"
|
|
268
|
+
:disabled="item.disabled"
|
|
269
|
+
:readonly="readonly"
|
|
270
|
+
@change="() => onInputChange(item)"
|
|
271
|
+
/>
|
|
272
|
+
<span class="bb-table-check__label-text sr-only">{{
|
|
273
|
+
item.accessibleLabel
|
|
274
|
+
}}</span>
|
|
275
|
+
</label>
|
|
276
|
+
|
|
277
|
+
<label
|
|
278
|
+
v-else
|
|
279
|
+
class="bb-table-radio__label"
|
|
280
|
+
:class="{
|
|
281
|
+
'bb-table-radio__label--disabled': item.disabled,
|
|
282
|
+
}"
|
|
283
|
+
>
|
|
284
|
+
<BaseRadio
|
|
285
|
+
:checked="item.selected"
|
|
286
|
+
class="bb-table-radio"
|
|
287
|
+
:disabled="item.disabled"
|
|
288
|
+
:name="randomName"
|
|
289
|
+
:readonly="readonly"
|
|
290
|
+
:value="item.value"
|
|
291
|
+
@change="() => onInputChange(item)"
|
|
292
|
+
/>
|
|
293
|
+
<span class="bb-table-radio__label-text sr-only">{{
|
|
294
|
+
item.accessibleLabel
|
|
295
|
+
}}</span>
|
|
296
|
+
</label>
|
|
297
|
+
</slot>
|
|
298
|
+
</td>
|
|
299
|
+
<td
|
|
300
|
+
v-for="col in item.cols"
|
|
301
|
+
:key="col.key"
|
|
302
|
+
class="bb-table-data__cell"
|
|
303
|
+
:class="col.classes"
|
|
304
|
+
>
|
|
305
|
+
<!-- @vue-ignore -->
|
|
306
|
+
<slot
|
|
307
|
+
:classes="col.classes"
|
|
308
|
+
:content="col.content"
|
|
309
|
+
:expanded="item.expanded"
|
|
310
|
+
:item="item.item"
|
|
311
|
+
:name="col.slotName"
|
|
312
|
+
:expand-props="getExpandControllerProps(item)"
|
|
313
|
+
:toggle-expanded="() => toggleExpandedFor(item.valueHash)"
|
|
314
|
+
:value="item.value"
|
|
315
|
+
>{{ col.content }}</slot
|
|
316
|
+
>
|
|
317
|
+
</td>
|
|
318
|
+
<td
|
|
319
|
+
v-if="actions"
|
|
320
|
+
class="bb-table__cell bb-table__cell--actions"
|
|
321
|
+
:class="tdClass"
|
|
322
|
+
>
|
|
323
|
+
<!-- @vue-ignore -->
|
|
324
|
+
<slot
|
|
325
|
+
:expanded="item.expanded"
|
|
326
|
+
:item="item.item"
|
|
327
|
+
:name="'actions'"
|
|
328
|
+
:expand-props="getExpandControllerProps(item)"
|
|
329
|
+
:toggle-expanded="() => toggleExpandedFor(item.valueHash)"
|
|
330
|
+
:value="item.value"
|
|
331
|
+
></slot>
|
|
332
|
+
</td>
|
|
333
|
+
</tr>
|
|
334
|
+
<tr
|
|
335
|
+
v-if="item.expanded"
|
|
336
|
+
:aria-rowindex="
|
|
337
|
+
hasProvidedAccessibilityData && item.rowIndex
|
|
338
|
+
? item.rowIndex + 1
|
|
339
|
+
: undefined
|
|
340
|
+
"
|
|
341
|
+
:id="`expanded_${item.valueHash}`"
|
|
342
|
+
class="bb-table-expand__row"
|
|
343
|
+
>
|
|
344
|
+
<td
|
|
345
|
+
:colspan="replacementContentSpan"
|
|
346
|
+
class="bb-table-expand__cell"
|
|
347
|
+
>
|
|
348
|
+
<!-- @vue-ignore -->
|
|
349
|
+
<slot
|
|
350
|
+
:expanded="item.expanded"
|
|
351
|
+
:item="item.item"
|
|
352
|
+
:name="'expand'"
|
|
353
|
+
:expand-props="getExpandControllerProps(item)"
|
|
354
|
+
:toggle-expanded="() => toggleExpandedFor(item.valueHash)"
|
|
355
|
+
:value="item.value"
|
|
356
|
+
></slot>
|
|
357
|
+
</td>
|
|
358
|
+
</tr>
|
|
359
|
+
</template>
|
|
360
|
+
</slot>
|
|
361
|
+
</tbody>
|
|
362
|
+
<tfoot>
|
|
363
|
+
<!-- @vue-ignore -->
|
|
364
|
+
<slot name="tfoot"></slot>
|
|
365
|
+
</tfoot>
|
|
366
|
+
</table>
|
|
367
|
+
<input v-for="input in hiddenInputs" :key="input.value" v-bind="input" />
|
|
368
|
+
</component>
|
|
369
|
+
</template>
|
|
370
|
+
|
|
371
|
+
<script
|
|
372
|
+
setup
|
|
373
|
+
lang="ts"
|
|
374
|
+
generic="Item = any, T extends ItemKey<Item> = string & {}"
|
|
375
|
+
>
|
|
376
|
+
import { computed, reactive, ref, toRef, watch } from 'vue';
|
|
377
|
+
import { clamp } from '@/utilities/functions/clamp';
|
|
378
|
+
import { hash } from '@/utilities/functions/hash';
|
|
379
|
+
import { isNil } from '@/utilities/functions/isNil';
|
|
380
|
+
import { when } from '@/utilities/functions/when';
|
|
381
|
+
import { useId } from '@/composables/useId';
|
|
382
|
+
import { useItemValue } from '@/composables/useItemValue';
|
|
383
|
+
import { useItemsGetter } from '@/composables/useItemsGetter';
|
|
384
|
+
import { usePrefill } from '@/composables/usePrefill';
|
|
385
|
+
import { useIndexById } from '@/composables/useIndexById';
|
|
386
|
+
import { useBaseOptions } from '@/composables/useBaseOptions';
|
|
387
|
+
import { useHashedWatcher } from '@/composables/useHashedWatcher';
|
|
388
|
+
import { useLocale } from '@/composables/useLocale';
|
|
389
|
+
import BaseCheckbox from '../BaseCheckbox/BaseCheckbox.vue';
|
|
390
|
+
import BaseRadio from '../BaseRadio/BaseRadio.vue';
|
|
391
|
+
import type { Option as BaseOption } from '@/types/Option';
|
|
392
|
+
import type { Classes } from '@/types/Classes';
|
|
393
|
+
import type { ColumnName } from '@/types/ColumnName';
|
|
394
|
+
import type { PrefixWith } from '@/types/PrefixWith';
|
|
395
|
+
import type {
|
|
396
|
+
BbTableColumn,
|
|
397
|
+
BbTableEvents,
|
|
398
|
+
BbTableProps,
|
|
399
|
+
BbTableSlots,
|
|
400
|
+
ExpandControllerProps,
|
|
401
|
+
ItemKey,
|
|
402
|
+
MappedCell,
|
|
403
|
+
MappedHeader,
|
|
404
|
+
MappedItem,
|
|
405
|
+
} from './types';
|
|
406
|
+
import {
|
|
407
|
+
applyFixedTableColumns,
|
|
408
|
+
columnKeyToSlotName,
|
|
409
|
+
mergeCellClasses,
|
|
410
|
+
mergeHeaderClasses,
|
|
411
|
+
} from './utils';
|
|
412
|
+
import { useLogger } from '@/composables/useLogger';
|
|
413
|
+
import { isEmpty } from '@/utilities/functions/empty';
|
|
414
|
+
|
|
415
|
+
const { getItemValue } = useItemValue();
|
|
416
|
+
|
|
417
|
+
/** Temporary name for selection inputs; hidden inputs handle real submission. */
|
|
418
|
+
const randomName = useId().id.value;
|
|
419
|
+
|
|
420
|
+
type InternalColumn<K extends string> = Omit<BbTableColumn<Item>, 'key'> & {
|
|
421
|
+
key: K;
|
|
422
|
+
};
|
|
423
|
+
|
|
424
|
+
type InternalProps<K extends string> = Omit<BbTableProps<Item>, 'columns'> & {
|
|
425
|
+
columns: InternalColumn<K>[];
|
|
426
|
+
};
|
|
427
|
+
|
|
428
|
+
const props = withDefaults(defineProps<InternalProps<T>>(), {
|
|
429
|
+
align: 'left',
|
|
430
|
+
actionsText: 'Azioni',
|
|
431
|
+
allowSelectAll: true,
|
|
432
|
+
columns: () => [],
|
|
433
|
+
dependencies: () => [],
|
|
434
|
+
depsDebounceTime: 0,
|
|
435
|
+
fixedColumns: () => [],
|
|
436
|
+
items: () => [],
|
|
437
|
+
max: Infinity,
|
|
438
|
+
multiple: true,
|
|
439
|
+
modelValue: () => [],
|
|
440
|
+
unselectedItems: () => [],
|
|
441
|
+
});
|
|
442
|
+
|
|
443
|
+
const emit = defineEmits<BbTableEvents>();
|
|
444
|
+
|
|
445
|
+
type InferredBodySlots = ColumnName<T>;
|
|
446
|
+
type InferredHeaderSlots = PrefixWith<ColumnName<T>, 'header:'>;
|
|
447
|
+
|
|
448
|
+
defineSlots<
|
|
449
|
+
BbTableSlots<Item> & {
|
|
450
|
+
[K in InferredBodySlots]?: (props: {
|
|
451
|
+
classes?: Classes;
|
|
452
|
+
content?: any;
|
|
453
|
+
expanded?: boolean;
|
|
454
|
+
expandProps?: ExpandControllerProps;
|
|
455
|
+
toggleExpanded?: () => void;
|
|
456
|
+
item: Item;
|
|
457
|
+
value?: any;
|
|
458
|
+
}) => any;
|
|
459
|
+
} & {
|
|
460
|
+
[K in InferredHeaderSlots]?: (props: {
|
|
461
|
+
classes?: Classes;
|
|
462
|
+
content?: any;
|
|
463
|
+
items?: Item[];
|
|
464
|
+
label?: string;
|
|
465
|
+
}) => any;
|
|
466
|
+
}
|
|
467
|
+
>();
|
|
468
|
+
|
|
469
|
+
if (props.multiple && !Array.isArray(props.modelValue)) {
|
|
470
|
+
const logger = useLogger();
|
|
471
|
+
logger.throw(
|
|
472
|
+
'BbTable is set for multiple selection but modelValue is not an array.'
|
|
473
|
+
);
|
|
474
|
+
}
|
|
475
|
+
|
|
476
|
+
const { t } = useLocale();
|
|
477
|
+
|
|
478
|
+
const tableRef = ref<HTMLTableElement>();
|
|
479
|
+
|
|
480
|
+
/** Builds accessible label for selection controls from row content. */
|
|
481
|
+
const getAccessibleLabel = (columns: MappedCell[]) =>
|
|
482
|
+
[t('table.select').value, ...columns.map((col) => col.content)].join(' ');
|
|
483
|
+
|
|
484
|
+
const containerTag = computed(() => (props.selectable ? 'fieldset' : 'div'));
|
|
485
|
+
|
|
486
|
+
const loading = computed(() => props.loading || innerLoading.value);
|
|
487
|
+
|
|
488
|
+
const hasProvidedAccessibilityData = computed(
|
|
489
|
+
() => !isNil(props.page) && !isNil(props.perPage) && !isNil(props.totalItems)
|
|
490
|
+
);
|
|
491
|
+
|
|
492
|
+
const containerClass = computed(() => ({
|
|
493
|
+
'bb-table': true,
|
|
494
|
+
[`bb-table--align-${props.align}`]: true,
|
|
495
|
+
'bb-table--compact': props.compact,
|
|
496
|
+
'bb-table--fixed': props.fixed,
|
|
497
|
+
'bb-table--fixed-header': props.fixedHeaders,
|
|
498
|
+
'bb-table--loading': loading.value,
|
|
499
|
+
'bb-table--empty': !options.value.length,
|
|
500
|
+
'bb-table--selectable': !!props.selectable,
|
|
501
|
+
}));
|
|
502
|
+
|
|
503
|
+
const replacementContentSpan = computed(
|
|
504
|
+
() =>
|
|
505
|
+
props.columns.length + Number(!!props.selectable) + Number(!!props.actions)
|
|
506
|
+
);
|
|
507
|
+
|
|
508
|
+
const slotNamesByKey = computed(() =>
|
|
509
|
+
Object.fromEntries(
|
|
510
|
+
props.columns.map((col) => [col.key, columnKeyToSlotName(col.key)])
|
|
511
|
+
)
|
|
512
|
+
);
|
|
513
|
+
const {
|
|
514
|
+
getter,
|
|
515
|
+
items: internalItems,
|
|
516
|
+
loading: innerLoading,
|
|
517
|
+
} = useItemsGetter({
|
|
518
|
+
items: toRef(props, 'items'),
|
|
519
|
+
});
|
|
520
|
+
|
|
521
|
+
const { hasPrefilled } = usePrefill({
|
|
522
|
+
trigger: true,
|
|
523
|
+
fn: async (isPrefill) => {
|
|
524
|
+
await getter(isPrefill, props.modelValue);
|
|
525
|
+
},
|
|
526
|
+
});
|
|
527
|
+
|
|
528
|
+
const { data: modelValueIndexedByHash } = useIndexById({
|
|
529
|
+
items: toRef(props, 'modelValue'),
|
|
530
|
+
});
|
|
531
|
+
|
|
532
|
+
const { options } = useBaseOptions({
|
|
533
|
+
disabled: toRef(props, 'disabled'),
|
|
534
|
+
items: internalItems,
|
|
535
|
+
itemText: undefined,
|
|
536
|
+
itemValue: props.itemValue,
|
|
537
|
+
max: props.max,
|
|
538
|
+
selectable: true,
|
|
539
|
+
selectedIndexedByHash: modelValueIndexedByHash,
|
|
540
|
+
});
|
|
541
|
+
|
|
542
|
+
const onOptionSelected = async (option: BaseOption) => {
|
|
543
|
+
if (props.multiple) {
|
|
544
|
+
emit('update:modelValue', props.modelValue.concat(option.value));
|
|
545
|
+
} else {
|
|
546
|
+
emit('update:modelValue', option.value);
|
|
547
|
+
}
|
|
548
|
+
};
|
|
549
|
+
|
|
550
|
+
const onOptionUnselected = async (option: BaseOption) => {
|
|
551
|
+
if (props.multiple) {
|
|
552
|
+
const copy = { ...modelValueIndexedByHash.value };
|
|
553
|
+
delete copy[option.valueHash];
|
|
554
|
+
emit('update:modelValue', Object.values(copy));
|
|
555
|
+
} else {
|
|
556
|
+
emit('update:modelValue', null);
|
|
557
|
+
}
|
|
558
|
+
};
|
|
559
|
+
|
|
560
|
+
useHashedWatcher(
|
|
561
|
+
() => [props.dependencies, props.items],
|
|
562
|
+
async () => {
|
|
563
|
+
if (!hasPrefilled.value) {
|
|
564
|
+
return;
|
|
565
|
+
}
|
|
566
|
+
await getter(false, props.modelValue);
|
|
567
|
+
},
|
|
568
|
+
{
|
|
569
|
+
debounce: props.depsDebounceTime,
|
|
570
|
+
}
|
|
571
|
+
);
|
|
572
|
+
|
|
573
|
+
const mapColumnToCell = (
|
|
574
|
+
column: BbTableColumn<Item>,
|
|
575
|
+
item: BaseOption
|
|
576
|
+
): MappedCell => {
|
|
577
|
+
const slotName = slotNamesByKey.value[column.key];
|
|
578
|
+
const align = column.align ?? 'left';
|
|
579
|
+
let content = getItemValue(item.item, column.key);
|
|
580
|
+
|
|
581
|
+
if (column.formatter && (!isNil(content) || column.formatOnNull !== false)) {
|
|
582
|
+
content = column.formatter(content, column.key, item.item);
|
|
583
|
+
}
|
|
584
|
+
if (column.placeholder && isNil(content)) {
|
|
585
|
+
content = column.placeholder;
|
|
586
|
+
}
|
|
587
|
+
|
|
588
|
+
return {
|
|
589
|
+
align,
|
|
590
|
+
classes: mergeCellClasses(
|
|
591
|
+
[`bb-table-data__cell--${align}`],
|
|
592
|
+
props.tdClass,
|
|
593
|
+
column.tdClass,
|
|
594
|
+
content,
|
|
595
|
+
column.key,
|
|
596
|
+
item.item
|
|
597
|
+
),
|
|
598
|
+
content,
|
|
599
|
+
key: column.key,
|
|
600
|
+
label: column.label,
|
|
601
|
+
slotName,
|
|
602
|
+
};
|
|
603
|
+
};
|
|
604
|
+
|
|
605
|
+
const mappedHeaders = computed(() =>
|
|
606
|
+
props.columns.map((column: BbTableColumn<Item>): MappedHeader => {
|
|
607
|
+
const align = column.align ?? 'left';
|
|
608
|
+
const slotName = `header:${slotNamesByKey.value[column.key]}`;
|
|
609
|
+
const sortDirection = column.sorted
|
|
610
|
+
? column.sorted === 'asc'
|
|
611
|
+
? 'ascending'
|
|
612
|
+
: 'descending'
|
|
613
|
+
: undefined;
|
|
614
|
+
return {
|
|
615
|
+
align,
|
|
616
|
+
key: column.key,
|
|
617
|
+
label: column.label,
|
|
618
|
+
slotName,
|
|
619
|
+
classes: mergeHeaderClasses(
|
|
620
|
+
[`bb-table-header--${align}`],
|
|
621
|
+
props.thClass,
|
|
622
|
+
column.thClass
|
|
623
|
+
),
|
|
624
|
+
sortDirection,
|
|
625
|
+
};
|
|
626
|
+
})
|
|
627
|
+
);
|
|
628
|
+
|
|
629
|
+
const mappedItems = computed<MappedItem[]>(() => {
|
|
630
|
+
let expandedRows = 0;
|
|
631
|
+
return options.value.map((item: BaseOption, index: number): MappedItem => {
|
|
632
|
+
const disabled =
|
|
633
|
+
!props.selectable ||
|
|
634
|
+
(typeof props.selectable === 'function' &&
|
|
635
|
+
!props.selectable(item.item)) ||
|
|
636
|
+
!!item.disabled;
|
|
637
|
+
|
|
638
|
+
// How many rows have passed
|
|
639
|
+
const indexPageOffset = (props.page ?? 0 - 1) * (props.perPage ?? 0);
|
|
640
|
+
const headRowOffset = 1;
|
|
641
|
+
const increment = index + 1;
|
|
642
|
+
const rowIndex = indexPageOffset + headRowOffset + increment + expandedRows;
|
|
643
|
+
|
|
644
|
+
// Create a projection of the columns and run all formatter logic so
|
|
645
|
+
// we just display content in the template
|
|
646
|
+
const cols: MappedCell[] = props.columns.map((column) =>
|
|
647
|
+
mapColumnToCell(column, item)
|
|
648
|
+
);
|
|
649
|
+
const expanded = expandedItemsIndexedByHash.value[item.valueHash] ?? false;
|
|
650
|
+
if (expanded) {
|
|
651
|
+
expandedRows++;
|
|
652
|
+
}
|
|
653
|
+
const res = {
|
|
654
|
+
accessibleLabel: getAccessibleLabel(cols),
|
|
655
|
+
cols,
|
|
656
|
+
expanded,
|
|
657
|
+
onRowClick: (event: MouseEvent) =>
|
|
658
|
+
emit('click:row', event, item, !!item.selected),
|
|
659
|
+
onRowContextMenu: (event: MouseEvent) =>
|
|
660
|
+
emit('contextmenu:row', event, item, !!item.selected),
|
|
661
|
+
onRowDblClick: (event: MouseEvent) =>
|
|
662
|
+
emit('dblclick:row', event, item, !!item.selected),
|
|
663
|
+
item: item.item,
|
|
664
|
+
text: item.text,
|
|
665
|
+
rowIndex,
|
|
666
|
+
valueHash: item.valueHash,
|
|
667
|
+
value: item.value,
|
|
668
|
+
selected: item.selected,
|
|
669
|
+
disabled,
|
|
670
|
+
};
|
|
671
|
+
return res;
|
|
672
|
+
});
|
|
673
|
+
});
|
|
674
|
+
|
|
675
|
+
const selectAll = defineModel<boolean>('selectAll', {
|
|
676
|
+
required: false,
|
|
677
|
+
default: false,
|
|
678
|
+
});
|
|
679
|
+
|
|
680
|
+
const expandedItems = defineModel<any[]>('expandedItems', {
|
|
681
|
+
required: false,
|
|
682
|
+
default: () => [],
|
|
683
|
+
});
|
|
684
|
+
|
|
685
|
+
const { data: expandedItemsIndexedByHash } = useIndexById({
|
|
686
|
+
items: expandedItems,
|
|
687
|
+
});
|
|
688
|
+
|
|
689
|
+
const onExpandControllerKeydown = (event: KeyboardEvent, valueHash: string) => {
|
|
690
|
+
if (!(event.target instanceof HTMLElement)) return;
|
|
691
|
+
if (event.target instanceof HTMLButtonElement) return;
|
|
692
|
+
if (event.key !== 'Enter' && event.key !== ' ') return;
|
|
693
|
+
event.preventDefault();
|
|
694
|
+
toggleExpandedFor(valueHash);
|
|
695
|
+
};
|
|
696
|
+
|
|
697
|
+
const getExpandControllerProps = (item: MappedItem) => ({
|
|
698
|
+
'aria-controls': isNil(expandedItemsIndexedByHash.value[item.valueHash])
|
|
699
|
+
? undefined
|
|
700
|
+
: `expanded_${item.valueHash}`,
|
|
701
|
+
'aria-expanded': item.expanded ? 'true' : 'false',
|
|
702
|
+
onClick: (event: MouseEvent) => {
|
|
703
|
+
event.stopPropagation();
|
|
704
|
+
toggleExpandedFor(item.valueHash);
|
|
705
|
+
},
|
|
706
|
+
onKeydown: (event: KeyboardEvent) =>
|
|
707
|
+
onExpandControllerKeydown(event, item.valueHash),
|
|
708
|
+
});
|
|
709
|
+
|
|
710
|
+
const toggleExpandedFor = (valueHash: string) => {
|
|
711
|
+
const linkedOption = options.value.find((o) => o.valueHash === valueHash);
|
|
712
|
+
if (!linkedOption) return;
|
|
713
|
+
if (valueHash in expandedItemsIndexedByHash.value) {
|
|
714
|
+
expandedItems.value = expandedItems.value.filter(
|
|
715
|
+
(o) => hash(o) !== valueHash
|
|
716
|
+
);
|
|
717
|
+
} else {
|
|
718
|
+
expandedItems.value = [...expandedItems.value, linkedOption.value];
|
|
719
|
+
}
|
|
720
|
+
};
|
|
721
|
+
|
|
722
|
+
watch(selectAll, () => {
|
|
723
|
+
unselectedItems.clear();
|
|
724
|
+
emit('update:unselectedItems', []);
|
|
725
|
+
emit('update:modelValue', []);
|
|
726
|
+
});
|
|
727
|
+
|
|
728
|
+
const indeterminate = computed(() => {
|
|
729
|
+
if (props.multiple && props.modelValue.length > 0 && !props.selectAll) {
|
|
730
|
+
return true;
|
|
731
|
+
}
|
|
732
|
+
if (selectAll.value && unselectedItems.size > 0) {
|
|
733
|
+
return true;
|
|
734
|
+
}
|
|
735
|
+
return false;
|
|
736
|
+
});
|
|
737
|
+
|
|
738
|
+
const unselectedItems = reactive(new Set<string>());
|
|
739
|
+
watch(
|
|
740
|
+
() => props.unselectedItems,
|
|
741
|
+
() => {
|
|
742
|
+
unselectedItems.clear();
|
|
743
|
+
props.unselectedItems.forEach((i) => {
|
|
744
|
+
unselectedItems.add(hash(i));
|
|
745
|
+
});
|
|
746
|
+
}
|
|
747
|
+
);
|
|
748
|
+
|
|
749
|
+
const onInputChange = (item: BaseOption) => {
|
|
750
|
+
if (isSelected(item)) {
|
|
751
|
+
onOptionUnselected(item);
|
|
752
|
+
emit('item:unselected', item.value);
|
|
753
|
+
unselectedItems.add(item.valueHash);
|
|
754
|
+
emit('update:unselectedItems', [...props.unselectedItems, item.value]);
|
|
755
|
+
return;
|
|
756
|
+
}
|
|
757
|
+
if (!selectAll.value) {
|
|
758
|
+
onOptionSelected(item);
|
|
759
|
+
}
|
|
760
|
+
emit('item:selected', item.value);
|
|
761
|
+
unselectedItems.delete(item.valueHash);
|
|
762
|
+
emit(
|
|
763
|
+
'update:unselectedItems',
|
|
764
|
+
props.unselectedItems.filter((i) => hash(i) !== hash(item.value))
|
|
765
|
+
);
|
|
766
|
+
};
|
|
767
|
+
|
|
768
|
+
const isSelected = (item: BaseOption): boolean => {
|
|
769
|
+
if (unselectedItems.has(item.valueHash)) return false;
|
|
770
|
+
return item.selected || selectAll.value;
|
|
771
|
+
};
|
|
772
|
+
|
|
773
|
+
/**
|
|
774
|
+
* When using this component for submission we add a bunch of hidden inputs
|
|
775
|
+
* so the submitted inputs is on par with v-model
|
|
776
|
+
*/
|
|
777
|
+
|
|
778
|
+
/**
|
|
779
|
+
* This is used to keep the value compatible to common html expected values.
|
|
780
|
+
* Convert to string everything that's not but do not double encode strings
|
|
781
|
+
*/
|
|
782
|
+
const makeInputValue = when(
|
|
783
|
+
(item: unknown) => typeof item !== 'string',
|
|
784
|
+
JSON.stringify
|
|
785
|
+
);
|
|
786
|
+
const hiddenInputs = computed(() =>
|
|
787
|
+
[].concat(props.modelValue ?? []).map((current: unknown) => ({
|
|
788
|
+
disabled: props.disabled,
|
|
789
|
+
name: props.name,
|
|
790
|
+
type: 'hidden' as const,
|
|
791
|
+
value: makeInputValue(current),
|
|
792
|
+
}))
|
|
793
|
+
);
|
|
794
|
+
|
|
795
|
+
/** Varied line widths for skeleton (percent) to avoid a mechanical look */
|
|
796
|
+
const skeletonLineWidths = [70, 45, 85, 55];
|
|
797
|
+
|
|
798
|
+
const skeletonLength = computed(() =>
|
|
799
|
+
clamp(options.value.length || props.columns.length || 1, 4, 10)
|
|
800
|
+
);
|
|
801
|
+
|
|
802
|
+
watch(
|
|
803
|
+
() => [mappedItems.value, props.fixedColumns],
|
|
804
|
+
() => {
|
|
805
|
+
if (tableRef.value && props.fixedColumns?.length) {
|
|
806
|
+
applyFixedTableColumns(tableRef.value, props.fixedColumns);
|
|
807
|
+
}
|
|
808
|
+
},
|
|
809
|
+
{ flush: 'post' }
|
|
810
|
+
);
|
|
811
|
+
</script>
|
|
812
|
+
|
|
813
|
+
<style lang="postcss">
|
|
814
|
+
@import './index.css';
|
|
815
|
+
</style>
|
|
816
|
+
```
|
|
817
|
+
|
|
818
|
+
## Types
|
|
819
|
+
|
|
820
|
+
```ts
|
|
821
|
+
import type { Classes } from '@/types/Classes';
|
|
822
|
+
import type { Option } from '@/types/Option';
|
|
823
|
+
import type { InputHTMLAttributes } from 'vue';
|
|
824
|
+
|
|
825
|
+
/**
|
|
826
|
+
* Recursively builds dot-notation paths from a type's keys.
|
|
827
|
+
* Depth-limited to 3 levels to avoid compiler performance issues.
|
|
828
|
+
*/
|
|
829
|
+
type NestedPaths<T, Depth extends unknown[] = []> = Depth['length'] extends 3
|
|
830
|
+
? never
|
|
831
|
+
: 0 extends 1 & T
|
|
832
|
+
? string
|
|
833
|
+
: T extends object
|
|
834
|
+
? T extends any[] | Date | Function | RegExp | Map<any, any> | Set<any>
|
|
835
|
+
? never
|
|
836
|
+
: {
|
|
837
|
+
[K in Extract<keyof T, string>]:
|
|
838
|
+
| K
|
|
839
|
+
| `${K}.${NestedPaths<NonNullable<T[K]>, [...Depth, unknown]>}`;
|
|
840
|
+
}[Extract<keyof T, string>]
|
|
841
|
+
: never;
|
|
842
|
+
|
|
843
|
+
/**
|
|
844
|
+
* Suggested keys for a column derived from an Item type.
|
|
845
|
+
* Provides autocomplete for nested dot-notation paths (up to 3 levels)
|
|
846
|
+
* while still allowing arbitrary string keys for virtual columns.
|
|
847
|
+
*/
|
|
848
|
+
export type ItemKey<Item = any> = NestedPaths<Item> | (string & {});
|
|
849
|
+
|
|
850
|
+
/**
|
|
851
|
+
* Skeleton placeholder style for the loading state.
|
|
852
|
+
* Matches the expected content type for a better loading experience.
|
|
853
|
+
*/
|
|
854
|
+
export type SkeletonType =
|
|
855
|
+
| 'text'
|
|
856
|
+
| 'avatar'
|
|
857
|
+
| 'avatar-text'
|
|
858
|
+
| 'image'
|
|
859
|
+
| 'badge';
|
|
860
|
+
|
|
861
|
+
export type BaseColumn<Item = any> = {
|
|
862
|
+
/**
|
|
863
|
+
* When set to false the formatter will not run on nullish values.
|
|
864
|
+
* By default is true so you can create virtual columns with keys that do not
|
|
865
|
+
* reference a prop in the `item` and still extract data from the other
|
|
866
|
+
* arguments in the formatting function.
|
|
867
|
+
*/
|
|
868
|
+
formatOnNull?: boolean;
|
|
869
|
+
|
|
870
|
+
/**
|
|
871
|
+
* Formatting function used to generate enhanced content.
|
|
872
|
+
* @param content The content generated by the extraction of `Item[key]`
|
|
873
|
+
* @param key Key of the column taken from the column definition.
|
|
874
|
+
* @param item Item of the row.
|
|
875
|
+
*/
|
|
876
|
+
formatter?: (content: any, key: string, item: Item) => any;
|
|
877
|
+
|
|
878
|
+
/**
|
|
879
|
+
* Key identifying the column.
|
|
880
|
+
*/
|
|
881
|
+
key: ItemKey<Item>;
|
|
882
|
+
|
|
883
|
+
/**
|
|
884
|
+
* Text used in the header for this column.
|
|
885
|
+
*/
|
|
886
|
+
label: string;
|
|
887
|
+
|
|
888
|
+
/**
|
|
889
|
+
* Placeholder used when the pipeline returns null content.
|
|
890
|
+
*/
|
|
891
|
+
placeholder?: string;
|
|
892
|
+
};
|
|
893
|
+
|
|
894
|
+
/**
|
|
895
|
+
* Column definition for BbTable. Controls data extraction, formatting, alignment, and styling.
|
|
896
|
+
*/
|
|
897
|
+
export type BbTableColumn<Item = any> = BaseColumn<Item> & {
|
|
898
|
+
/**
|
|
899
|
+
* Text alignment of the column.
|
|
900
|
+
*/
|
|
901
|
+
align?: 'left' | 'right' | 'center';
|
|
902
|
+
|
|
903
|
+
/**
|
|
904
|
+
* Skeleton placeholder style shown during loading. Defaults to `'text'`.
|
|
905
|
+
*/
|
|
906
|
+
skeleton?: SkeletonType;
|
|
907
|
+
|
|
908
|
+
/**
|
|
909
|
+
* Defines the sorting direction of the column.
|
|
910
|
+
*/
|
|
911
|
+
sorted?: 'asc' | 'desc';
|
|
912
|
+
|
|
913
|
+
/**
|
|
914
|
+
* Defines the classes to be passed to the `<td>` elements. Can also be a function for dynamic values.
|
|
915
|
+
*/
|
|
916
|
+
tdClass?: ColumnClasses<Item>;
|
|
917
|
+
|
|
918
|
+
/**
|
|
919
|
+
* Defines the classes to be passed to the `<th>`.
|
|
920
|
+
*/
|
|
921
|
+
thClass?: Classes;
|
|
922
|
+
};
|
|
923
|
+
|
|
924
|
+
export type BbTableProps<Item = any> = {
|
|
925
|
+
/**
|
|
926
|
+
* Function that accepts the columns and the current item as
|
|
927
|
+
* arguments and returns a label to be used for accessibility purposes.
|
|
928
|
+
*/
|
|
929
|
+
accessibleLabel?: (columns: MappedCell[], item: any) => string;
|
|
930
|
+
|
|
931
|
+
/**
|
|
932
|
+
* Displays the actions column.
|
|
933
|
+
*/
|
|
934
|
+
actions?: boolean;
|
|
935
|
+
|
|
936
|
+
/**
|
|
937
|
+
* Label used in the header of the actions column.
|
|
938
|
+
*/
|
|
939
|
+
actionsText?: string;
|
|
940
|
+
|
|
941
|
+
/**
|
|
942
|
+
* Text alignment of the columns.
|
|
943
|
+
*/
|
|
944
|
+
align?: 'left' | 'center' | 'right';
|
|
945
|
+
|
|
946
|
+
/**
|
|
947
|
+
* Boolean that defines whether to display a "Select all" checkbox.
|
|
948
|
+
*/
|
|
949
|
+
allowSelectAll?: boolean;
|
|
950
|
+
|
|
951
|
+
/**
|
|
952
|
+
* Caption that describes the content of the table. Used for accessibility purposes.
|
|
953
|
+
*/
|
|
954
|
+
caption?: string;
|
|
955
|
+
|
|
956
|
+
/**
|
|
957
|
+
* Array of definitions of how the columns should be rendered.
|
|
958
|
+
*
|
|
959
|
+
*/
|
|
960
|
+
columns: BbTableColumn<Item>[];
|
|
961
|
+
|
|
962
|
+
/**
|
|
963
|
+
* Adds a CSS class that applies a compact style to the component.
|
|
964
|
+
*/
|
|
965
|
+
compact?: boolean;
|
|
966
|
+
|
|
967
|
+
/**
|
|
968
|
+
* Defines an array of dependencies that will trigger actions in the component upon change.
|
|
969
|
+
*/
|
|
970
|
+
dependencies?: any[];
|
|
971
|
+
|
|
972
|
+
/**
|
|
973
|
+
* Timeout used to debounce response to changes to dependencies.
|
|
974
|
+
*/
|
|
975
|
+
depsDebounceTime?: number;
|
|
976
|
+
|
|
977
|
+
/**
|
|
978
|
+
* Disables the component
|
|
979
|
+
*/
|
|
980
|
+
disabled?: boolean;
|
|
981
|
+
|
|
982
|
+
/**
|
|
983
|
+
* Boolean that defines whether to display or hide the caption.
|
|
984
|
+
* By default is true and the caption is hidden.
|
|
985
|
+
*/
|
|
986
|
+
displayCaption?: boolean;
|
|
987
|
+
|
|
988
|
+
/**
|
|
989
|
+
* Defines the table layout as fixed
|
|
990
|
+
* making each column take up the same amount of space.
|
|
991
|
+
*/
|
|
992
|
+
fixed?: boolean;
|
|
993
|
+
|
|
994
|
+
/**
|
|
995
|
+
* Definition for which column should be fixed.
|
|
996
|
+
* It can be an array of index of the column to fix on the left side of the table or
|
|
997
|
+
* an array of objects indicating the index and the position `left` or `right` where to affix the columns.
|
|
998
|
+
*/
|
|
999
|
+
fixedColumns?: (number | { index: number; position: 'left' | 'right' })[];
|
|
1000
|
+
|
|
1001
|
+
/**
|
|
1002
|
+
* Boolean that sets the headers as sticky to the top of the table.
|
|
1003
|
+
*/
|
|
1004
|
+
fixedHeaders?: boolean;
|
|
1005
|
+
|
|
1006
|
+
items:
|
|
1007
|
+
| Item[]
|
|
1008
|
+
| ((prefill: boolean, modelValue?: any[]) => Promise<Item[]>)
|
|
1009
|
+
| ((prefill: boolean, modelValue?: any[]) => Item[]);
|
|
1010
|
+
|
|
1011
|
+
itemValue?: string | ((item: Item) => any);
|
|
1012
|
+
|
|
1013
|
+
/**
|
|
1014
|
+
* Text content of the legend.
|
|
1015
|
+
*/
|
|
1016
|
+
legend?: string;
|
|
1017
|
+
|
|
1018
|
+
/**
|
|
1019
|
+
* Sets the component in a loading state, usually triggering some visual styles.
|
|
1020
|
+
*/
|
|
1021
|
+
loading?: boolean;
|
|
1022
|
+
|
|
1023
|
+
/**
|
|
1024
|
+
* String displayed while items are being loaded.
|
|
1025
|
+
*/
|
|
1026
|
+
loadingText?: string;
|
|
1027
|
+
|
|
1028
|
+
/**
|
|
1029
|
+
* Maximum number of items that can be selected.
|
|
1030
|
+
*/
|
|
1031
|
+
max?: number;
|
|
1032
|
+
|
|
1033
|
+
/**
|
|
1034
|
+
* Used by v-model. Can be any serializable type.
|
|
1035
|
+
*/
|
|
1036
|
+
modelValue?: any;
|
|
1037
|
+
|
|
1038
|
+
/**
|
|
1039
|
+
* Allows the selection of multiple items.
|
|
1040
|
+
*/
|
|
1041
|
+
multiple?: boolean;
|
|
1042
|
+
|
|
1043
|
+
/**
|
|
1044
|
+
* Defines the name of the input.
|
|
1045
|
+
*/
|
|
1046
|
+
name?: InputHTMLAttributes['name'];
|
|
1047
|
+
|
|
1048
|
+
/**
|
|
1049
|
+
* String displayed when there are no items to display.
|
|
1050
|
+
*/
|
|
1051
|
+
noDataText?: string;
|
|
1052
|
+
|
|
1053
|
+
/**
|
|
1054
|
+
* Current page number starting from 1, used for accessibility purposes.
|
|
1055
|
+
*/
|
|
1056
|
+
page?: number;
|
|
1057
|
+
|
|
1058
|
+
/**
|
|
1059
|
+
* Number of items per page, used for accessibility purposes.
|
|
1060
|
+
*/
|
|
1061
|
+
perPage?: number;
|
|
1062
|
+
|
|
1063
|
+
/**
|
|
1064
|
+
* Sets the input in a readonly state.
|
|
1065
|
+
*/
|
|
1066
|
+
readonly?: boolean;
|
|
1067
|
+
|
|
1068
|
+
/**
|
|
1069
|
+
* Defines whether the "Select all" checkbox is checked.
|
|
1070
|
+
*/
|
|
1071
|
+
selectAll?: boolean;
|
|
1072
|
+
|
|
1073
|
+
/**
|
|
1074
|
+
* Defines whether the table is selectable.
|
|
1075
|
+
* Can be a global boolean that affects all rows or a function
|
|
1076
|
+
* that accepts an item and returns a boolean that only affects that item.
|
|
1077
|
+
*/
|
|
1078
|
+
selectable?: boolean | ((item: Item) => boolean);
|
|
1079
|
+
|
|
1080
|
+
/**
|
|
1081
|
+
* Text of the label used by the "Select all" boolean.
|
|
1082
|
+
*/
|
|
1083
|
+
selectAllLabel?: string;
|
|
1084
|
+
|
|
1085
|
+
/**
|
|
1086
|
+
* Text of the header used for the radio inputs when the table is not `multiple`.
|
|
1087
|
+
*/
|
|
1088
|
+
selectText?: string;
|
|
1089
|
+
|
|
1090
|
+
/**
|
|
1091
|
+
* Defines the classes to be passed to the `<td>` elements. Can also be a function for dynamic values.
|
|
1092
|
+
*/
|
|
1093
|
+
tdClass?: ColumnClasses<Item>;
|
|
1094
|
+
|
|
1095
|
+
/**
|
|
1096
|
+
* Defines the classes to be passed to the `<th>`.
|
|
1097
|
+
*/
|
|
1098
|
+
thClass?: Classes;
|
|
1099
|
+
|
|
1100
|
+
/**
|
|
1101
|
+
* Total number of items there is.
|
|
1102
|
+
*/
|
|
1103
|
+
totalItems?: number;
|
|
1104
|
+
|
|
1105
|
+
/**
|
|
1106
|
+
* Items that are not selected.
|
|
1107
|
+
*/
|
|
1108
|
+
unselectedItems?: any[];
|
|
1109
|
+
};
|
|
1110
|
+
|
|
1111
|
+
/**
|
|
1112
|
+
* We allow table data classes to be a function so it can depend on the item
|
|
1113
|
+
*/
|
|
1114
|
+
export type ColumnClasses<Item = any> =
|
|
1115
|
+
| Classes
|
|
1116
|
+
| ((content: any, key: string, item: Item) => Classes);
|
|
1117
|
+
|
|
1118
|
+
/**
|
|
1119
|
+
* Projection that represents a row of cells with flags
|
|
1120
|
+
* linked to the state of the item
|
|
1121
|
+
*/
|
|
1122
|
+
export type MappedItem = Option & {
|
|
1123
|
+
accessibleLabel: string;
|
|
1124
|
+
cols: MappedCell[];
|
|
1125
|
+
expanded: boolean;
|
|
1126
|
+
onRowClick: (event: MouseEvent) => void;
|
|
1127
|
+
onRowContextMenu: (event: MouseEvent) => void;
|
|
1128
|
+
onRowDblClick: (event: MouseEvent) => void;
|
|
1129
|
+
rowIndex: number | undefined;
|
|
1130
|
+
};
|
|
1131
|
+
|
|
1132
|
+
/**
|
|
1133
|
+
* Projection that represents a header
|
|
1134
|
+
*/
|
|
1135
|
+
export type MappedHeader = {
|
|
1136
|
+
align: HTMLTableCellElement['align'];
|
|
1137
|
+
classes?: Classes;
|
|
1138
|
+
key: string;
|
|
1139
|
+
label: string;
|
|
1140
|
+
slotName: string;
|
|
1141
|
+
sortDirection?: 'ascending' | 'descending';
|
|
1142
|
+
};
|
|
1143
|
+
|
|
1144
|
+
/**
|
|
1145
|
+
* Projection that represents a cell of data for display.
|
|
1146
|
+
*/
|
|
1147
|
+
export type MappedCell = {
|
|
1148
|
+
align: string;
|
|
1149
|
+
classes: Classes;
|
|
1150
|
+
content: any;
|
|
1151
|
+
key: string;
|
|
1152
|
+
label: string;
|
|
1153
|
+
slotName: string;
|
|
1154
|
+
};
|
|
1155
|
+
|
|
1156
|
+
export type ExpandControllerProps = {
|
|
1157
|
+
'aria-controls'?: string;
|
|
1158
|
+
'aria-expanded': 'true' | 'false';
|
|
1159
|
+
onClick: () => void;
|
|
1160
|
+
onKeydown: (event: KeyboardEvent) => void;
|
|
1161
|
+
};
|
|
1162
|
+
|
|
1163
|
+
export type BbTableEvents = {
|
|
1164
|
+
(e: 'click:row', event: MouseEvent, item: any, selected: boolean): void;
|
|
1165
|
+
(e: 'contextmenu:row', event: MouseEvent, item: any, selected: boolean): void;
|
|
1166
|
+
(e: 'dblclick:row', event: MouseEvent, item: any, selected: boolean): void;
|
|
1167
|
+
(e: 'update:modelValue', value: any): void;
|
|
1168
|
+
(e: 'update:selectAll', value: boolean): void;
|
|
1169
|
+
(e: 'update:expandedItems', value: any[]): void;
|
|
1170
|
+
(e: 'update:unselectedItems', value: any[]): void;
|
|
1171
|
+
(e: 'item:selected', value: any): void;
|
|
1172
|
+
(e: 'item:unselected', value: any): void;
|
|
1173
|
+
};
|
|
1174
|
+
|
|
1175
|
+
export type BbTableSlots<Item = any> = {
|
|
1176
|
+
/**
|
|
1177
|
+
* Replaces the entire `<thead>` element. Use when you need full control over the header markup.
|
|
1178
|
+
*/
|
|
1179
|
+
thead?: (props: object) => any;
|
|
1180
|
+
/**
|
|
1181
|
+
* Replaces the entire `<tbody>` element. Use when you need full control over the body markup.
|
|
1182
|
+
*/
|
|
1183
|
+
tbody?: (props: object) => any;
|
|
1184
|
+
/**
|
|
1185
|
+
* Replaces the entire `<tfoot>` element. Use when you need full control over the footer markup.
|
|
1186
|
+
*/
|
|
1187
|
+
tfoot?: (props: object) => any;
|
|
1188
|
+
/**
|
|
1189
|
+
* Replaces the default selection header cell content (checkbox or radio label).
|
|
1190
|
+
* @param multiple - Whether the table allows multiple selection.
|
|
1191
|
+
* @param selectAll - Whether the "select all" checkbox is currently checked.
|
|
1192
|
+
* @param text - The accessible label text for the select-all control.
|
|
1193
|
+
*/
|
|
1194
|
+
'header:select'?: (props: {
|
|
1195
|
+
multiple: boolean;
|
|
1196
|
+
selectAll: boolean;
|
|
1197
|
+
text: string;
|
|
1198
|
+
}) => any;
|
|
1199
|
+
/**
|
|
1200
|
+
* Replaces the default actions header cell content.
|
|
1201
|
+
* @param text - The accessible label text for the actions column header.
|
|
1202
|
+
*/
|
|
1203
|
+
'header:actions'?: (props: { text: string }) => any;
|
|
1204
|
+
/**
|
|
1205
|
+
* Content shown while table rows are loading (replaces the skeleton rows).
|
|
1206
|
+
* @param items - The current (possibly stale) list of items, useful to match the previous row count.
|
|
1207
|
+
*/
|
|
1208
|
+
loading?: (props: { items: Item[] }) => any;
|
|
1209
|
+
/**
|
|
1210
|
+
* Content shown when the items list is empty and not loading.
|
|
1211
|
+
*/
|
|
1212
|
+
'no-data'?: (props: object) => any;
|
|
1213
|
+
/**
|
|
1214
|
+
* Content rendered in the actions cell for each row.
|
|
1215
|
+
* @param expanded - Whether this row is currently expanded.
|
|
1216
|
+
* @param expandProps - Bind these onto an expand-toggle button to wire up aria attributes and keyboard handling.
|
|
1217
|
+
* @param toggleExpanded - Toggles the expanded state for this row.
|
|
1218
|
+
* @param item - The raw item for this row.
|
|
1219
|
+
* @param value - The resolved value for this row.
|
|
1220
|
+
*/
|
|
1221
|
+
actions?: (props: {
|
|
1222
|
+
expanded?: boolean;
|
|
1223
|
+
expandProps?: ExpandControllerProps;
|
|
1224
|
+
toggleExpanded?: () => void;
|
|
1225
|
+
item: Item;
|
|
1226
|
+
value: any;
|
|
1227
|
+
}) => any;
|
|
1228
|
+
/**
|
|
1229
|
+
* Full-width expandable content row rendered below each main row when expanded.
|
|
1230
|
+
* @param expanded - Whether this row is currently expanded.
|
|
1231
|
+
* @param expandProps - Bind these onto an expand-toggle button to wire up aria attributes and keyboard handling.
|
|
1232
|
+
* @param toggleExpanded - Toggles the expanded state for this row.
|
|
1233
|
+
* @param item - The raw item for this row.
|
|
1234
|
+
* @param value - The resolved value for this row.
|
|
1235
|
+
*/
|
|
1236
|
+
expand?: (props: {
|
|
1237
|
+
expanded: boolean;
|
|
1238
|
+
expandProps?: ExpandControllerProps;
|
|
1239
|
+
toggleExpanded: () => void;
|
|
1240
|
+
item: Item;
|
|
1241
|
+
value: any;
|
|
1242
|
+
}) => any;
|
|
1243
|
+
/**
|
|
1244
|
+
* Replaces the default checkbox/radio in the selection cell for each row.
|
|
1245
|
+
* @param item - The raw item for this row.
|
|
1246
|
+
* @param value - The resolved value for this row.
|
|
1247
|
+
* @param checked - Whether this row is currently selected.
|
|
1248
|
+
* @param disabled - Whether this row's selection control is disabled.
|
|
1249
|
+
* @param inputName - The `name` attribute for the selection input.
|
|
1250
|
+
* @param readonly - Whether the selection control is read-only.
|
|
1251
|
+
*/
|
|
1252
|
+
select?: (props: {
|
|
1253
|
+
item: Item;
|
|
1254
|
+
value: any;
|
|
1255
|
+
checked: boolean;
|
|
1256
|
+
disabled: boolean;
|
|
1257
|
+
inputName: string;
|
|
1258
|
+
readonly: boolean;
|
|
1259
|
+
}) => any;
|
|
1260
|
+
} & {
|
|
1261
|
+
/**
|
|
1262
|
+
* Named slot for a specific column cell (`col-key`) or column header (`header:col-key`).
|
|
1263
|
+
* @param classes - CSS classes computed for the cell.
|
|
1264
|
+
* @param content - The formatted cell content.
|
|
1265
|
+
* @param expanded - Whether this row is currently expanded (body slots only).
|
|
1266
|
+
* @param expandProps - Bind these onto an expand-toggle button (body slots only).
|
|
1267
|
+
* @param toggleExpanded - Toggles the expanded state for this row (body slots only).
|
|
1268
|
+
* @param item - The raw item for this row (body slots only).
|
|
1269
|
+
* @param value - The resolved row value (body slots only).
|
|
1270
|
+
* @param items - The full items list (header slots only).
|
|
1271
|
+
* @param label - The column label (header slots only).
|
|
1272
|
+
*/
|
|
1273
|
+
[key: string]: (props: {
|
|
1274
|
+
classes?: Classes[];
|
|
1275
|
+
content?: any;
|
|
1276
|
+
expanded?: boolean;
|
|
1277
|
+
expandProps?: ExpandControllerProps;
|
|
1278
|
+
toggleExpanded?: () => void;
|
|
1279
|
+
item: Item;
|
|
1280
|
+
value?: any;
|
|
1281
|
+
items?: Item[];
|
|
1282
|
+
label?: string;
|
|
1283
|
+
}) => any;
|
|
1284
|
+
};
|
|
1285
|
+
```
|
|
1286
|
+
|
|
1287
|
+
## Styles
|
|
1288
|
+
|
|
1289
|
+
```css
|
|
1290
|
+
.bb-table {
|
|
1291
|
+
--padding-x: 16px;
|
|
1292
|
+
--padding-y: 8px;
|
|
1293
|
+
--actions-spacing: 8px;
|
|
1294
|
+
border-collapse: separate;
|
|
1295
|
+
border-spacing: 0;
|
|
1296
|
+
display: grid;
|
|
1297
|
+
overflow-x: auto;
|
|
1298
|
+
|
|
1299
|
+
position: relative;
|
|
1300
|
+
|
|
1301
|
+
&--align {
|
|
1302
|
+
&-left {
|
|
1303
|
+
text-align: left;
|
|
1304
|
+
}
|
|
1305
|
+
&-center {
|
|
1306
|
+
text-align: center;
|
|
1307
|
+
}
|
|
1308
|
+
&-right {
|
|
1309
|
+
text-align: right;
|
|
1310
|
+
}
|
|
1311
|
+
}
|
|
1312
|
+
|
|
1313
|
+
&--compact {
|
|
1314
|
+
--padding-x: 8px;
|
|
1315
|
+
--padding-y: 4px;
|
|
1316
|
+
}
|
|
1317
|
+
|
|
1318
|
+
&--fixed {
|
|
1319
|
+
table {
|
|
1320
|
+
table-layout: fixed;
|
|
1321
|
+
width: 100%;
|
|
1322
|
+
|
|
1323
|
+
thead {
|
|
1324
|
+
.bb-table-header--actions {
|
|
1325
|
+
width: auto;
|
|
1326
|
+
}
|
|
1327
|
+
}
|
|
1328
|
+
}
|
|
1329
|
+
}
|
|
1330
|
+
|
|
1331
|
+
&--fixed-header {
|
|
1332
|
+
table {
|
|
1333
|
+
thead {
|
|
1334
|
+
th {
|
|
1335
|
+
position: sticky;
|
|
1336
|
+
top: 0;
|
|
1337
|
+
z-index: 1;
|
|
1338
|
+
}
|
|
1339
|
+
th[style*='sticky'] {
|
|
1340
|
+
position: sticky;
|
|
1341
|
+
top: 0;
|
|
1342
|
+
z-index: 2;
|
|
1343
|
+
}
|
|
1344
|
+
}
|
|
1345
|
+
}
|
|
1346
|
+
}
|
|
1347
|
+
|
|
1348
|
+
&--loading {
|
|
1349
|
+
}
|
|
1350
|
+
|
|
1351
|
+
&--empty {
|
|
1352
|
+
}
|
|
1353
|
+
|
|
1354
|
+
&--selectable {
|
|
1355
|
+
tr {
|
|
1356
|
+
> .bb-table-data__cell--select {
|
|
1357
|
+
text-align: center;
|
|
1358
|
+
width: 0px;
|
|
1359
|
+
}
|
|
1360
|
+
}
|
|
1361
|
+
}
|
|
1362
|
+
|
|
1363
|
+
legend {
|
|
1364
|
+
}
|
|
1365
|
+
|
|
1366
|
+
table {
|
|
1367
|
+
min-width: 100%;
|
|
1368
|
+
}
|
|
1369
|
+
|
|
1370
|
+
.bb-table-caption {
|
|
1371
|
+
}
|
|
1372
|
+
|
|
1373
|
+
&-header-row {
|
|
1374
|
+
}
|
|
1375
|
+
|
|
1376
|
+
&-header {
|
|
1377
|
+
border-bottom: 1px solid var(--bb-border);
|
|
1378
|
+
color: color-mix(in srgb, var(--bb-text), transparent 40%);
|
|
1379
|
+
font-size: 14px;
|
|
1380
|
+
font-weight: 500;
|
|
1381
|
+
padding: var(--padding-y) var(--padding-x);
|
|
1382
|
+
|
|
1383
|
+
&--center {
|
|
1384
|
+
text-align: center;
|
|
1385
|
+
}
|
|
1386
|
+
|
|
1387
|
+
&--right {
|
|
1388
|
+
text-align: right;
|
|
1389
|
+
}
|
|
1390
|
+
|
|
1391
|
+
&--select {
|
|
1392
|
+
}
|
|
1393
|
+
|
|
1394
|
+
&--actions {
|
|
1395
|
+
width: 0;
|
|
1396
|
+
|
|
1397
|
+
.bb-table-header__content {
|
|
1398
|
+
}
|
|
1399
|
+
}
|
|
1400
|
+
|
|
1401
|
+
&__content {
|
|
1402
|
+
}
|
|
1403
|
+
}
|
|
1404
|
+
|
|
1405
|
+
tbody {
|
|
1406
|
+
tr {
|
|
1407
|
+
&:not(:last-child) {
|
|
1408
|
+
border-bottom: 1px solid var(--bb-border);
|
|
1409
|
+
}
|
|
1410
|
+
td {
|
|
1411
|
+
color: var(--bb-text);
|
|
1412
|
+
font-size: 14px;
|
|
1413
|
+
font-weight: 400;
|
|
1414
|
+
height: var(--bb-table-cell-h);
|
|
1415
|
+
padding: var(--padding-y) var(--padding-x);
|
|
1416
|
+
}
|
|
1417
|
+
|
|
1418
|
+
td.bb-table-expand__cell {
|
|
1419
|
+
padding: 0;
|
|
1420
|
+
}
|
|
1421
|
+
}
|
|
1422
|
+
}
|
|
1423
|
+
|
|
1424
|
+
&.bb-table--loading {
|
|
1425
|
+
.bb-table-loading__row {
|
|
1426
|
+
.bb-table-loading__cell {
|
|
1427
|
+
padding: 0 var(--padding-x) !important;
|
|
1428
|
+
vertical-align: top;
|
|
1429
|
+
}
|
|
1430
|
+
}
|
|
1431
|
+
|
|
1432
|
+
.bb-table-loading__row--sr-only {
|
|
1433
|
+
.bb-table-loading__cell {
|
|
1434
|
+
padding: 0 !important;
|
|
1435
|
+
border: none;
|
|
1436
|
+
height: 0;
|
|
1437
|
+
overflow: hidden;
|
|
1438
|
+
}
|
|
1439
|
+
}
|
|
1440
|
+
}
|
|
1441
|
+
|
|
1442
|
+
&-skeleton {
|
|
1443
|
+
&__row {
|
|
1444
|
+
}
|
|
1445
|
+
|
|
1446
|
+
&__cell {
|
|
1447
|
+
height: var(--bb-table-cell-h);
|
|
1448
|
+
overflow: hidden;
|
|
1449
|
+
padding: var(--padding-y) var(--padding-x);
|
|
1450
|
+
vertical-align: middle;
|
|
1451
|
+
|
|
1452
|
+
&--select,
|
|
1453
|
+
&--actions {
|
|
1454
|
+
text-align: center;
|
|
1455
|
+
width: 0;
|
|
1456
|
+
}
|
|
1457
|
+
}
|
|
1458
|
+
|
|
1459
|
+
&__cell-content {
|
|
1460
|
+
display: flex;
|
|
1461
|
+
flex-direction: column;
|
|
1462
|
+
gap: 6px;
|
|
1463
|
+
justify-content: center;
|
|
1464
|
+
max-height: calc(var(--bb-table-cell-h) - var(--padding-y) * 2);
|
|
1465
|
+
min-width: 96px;
|
|
1466
|
+
}
|
|
1467
|
+
|
|
1468
|
+
&__line {
|
|
1469
|
+
background: linear-gradient(
|
|
1470
|
+
90deg,
|
|
1471
|
+
var(--bb-border) 0%,
|
|
1472
|
+
var(--bb-border) 35%,
|
|
1473
|
+
color-mix(in srgb, var(--bb-border) 60%, white) 50%,
|
|
1474
|
+
var(--bb-border) 65%,
|
|
1475
|
+
var(--bb-border) 100%
|
|
1476
|
+
);
|
|
1477
|
+
background-size: 200% 100%;
|
|
1478
|
+
border-radius: 6px;
|
|
1479
|
+
flex-shrink: 0;
|
|
1480
|
+
height: 10px;
|
|
1481
|
+
animation: bb-table-skeleton-shimmer 1.8s ease-in-out infinite;
|
|
1482
|
+
}
|
|
1483
|
+
|
|
1484
|
+
@media (prefers-reduced-motion: reduce) {
|
|
1485
|
+
&__line {
|
|
1486
|
+
animation: none;
|
|
1487
|
+
background: var(--bb-border);
|
|
1488
|
+
}
|
|
1489
|
+
}
|
|
1490
|
+
|
|
1491
|
+
&__placeholder {
|
|
1492
|
+
background-color: var(--bb-border);
|
|
1493
|
+
border-radius: 6px;
|
|
1494
|
+
flex-shrink: 0;
|
|
1495
|
+
height: 22px;
|
|
1496
|
+
margin: 0 auto;
|
|
1497
|
+
min-width: 22px;
|
|
1498
|
+
width: 22px;
|
|
1499
|
+
}
|
|
1500
|
+
|
|
1501
|
+
&__avatar {
|
|
1502
|
+
aspect-ratio: 1;
|
|
1503
|
+
background-color: var(--bb-border);
|
|
1504
|
+
border-radius: 50%;
|
|
1505
|
+
flex-shrink: 0;
|
|
1506
|
+
height: calc(var(--bb-table-cell-h) - var(--padding-y) * 2);
|
|
1507
|
+
min-width: calc(var(--bb-table-cell-h) - var(--padding-y) * 2);
|
|
1508
|
+
width: calc(var(--bb-table-cell-h) - var(--padding-y) * 2);
|
|
1509
|
+
}
|
|
1510
|
+
|
|
1511
|
+
&__avatar-text {
|
|
1512
|
+
align-items: center;
|
|
1513
|
+
display: flex;
|
|
1514
|
+
gap: 12px;
|
|
1515
|
+
max-height: calc(var(--bb-table-cell-h) - var(--padding-y) * 2);
|
|
1516
|
+
min-width: 140px;
|
|
1517
|
+
}
|
|
1518
|
+
|
|
1519
|
+
&__avatar-text .bb-table-skeleton__avatar {
|
|
1520
|
+
width: calc(var(--bb-table-cell-h) - var(--padding-y) * 2);
|
|
1521
|
+
}
|
|
1522
|
+
|
|
1523
|
+
&__avatar-text .bb-table-skeleton__cell-content {
|
|
1524
|
+
flex: 1;
|
|
1525
|
+
min-width: 0;
|
|
1526
|
+
}
|
|
1527
|
+
|
|
1528
|
+
&__image {
|
|
1529
|
+
aspect-ratio: 4 / 3;
|
|
1530
|
+
background-color: var(--bb-border);
|
|
1531
|
+
border-radius: 8px;
|
|
1532
|
+
height: calc(var(--bb-table-cell-h) - var(--padding-y) * 2);
|
|
1533
|
+
min-width: 64px;
|
|
1534
|
+
width: auto;
|
|
1535
|
+
}
|
|
1536
|
+
|
|
1537
|
+
&__badge {
|
|
1538
|
+
background-color: var(--bb-border);
|
|
1539
|
+
border-radius: 999px;
|
|
1540
|
+
flex-shrink: 0;
|
|
1541
|
+
height: 26px;
|
|
1542
|
+
min-width: 72px;
|
|
1543
|
+
width: 88px;
|
|
1544
|
+
}
|
|
1545
|
+
}
|
|
1546
|
+
|
|
1547
|
+
@keyframes bb-table-skeleton-shimmer {
|
|
1548
|
+
0% {
|
|
1549
|
+
background-position: 200% 0;
|
|
1550
|
+
}
|
|
1551
|
+
100% {
|
|
1552
|
+
background-position: -200% 0;
|
|
1553
|
+
}
|
|
1554
|
+
}
|
|
1555
|
+
|
|
1556
|
+
&-no-data {
|
|
1557
|
+
&__row {
|
|
1558
|
+
}
|
|
1559
|
+
&__cell {
|
|
1560
|
+
}
|
|
1561
|
+
&__text {
|
|
1562
|
+
}
|
|
1563
|
+
}
|
|
1564
|
+
|
|
1565
|
+
&-data {
|
|
1566
|
+
&__row {
|
|
1567
|
+
}
|
|
1568
|
+
&__cell {
|
|
1569
|
+
&--center {
|
|
1570
|
+
text-align: center;
|
|
1571
|
+
}
|
|
1572
|
+
|
|
1573
|
+
&--right {
|
|
1574
|
+
text-align: right;
|
|
1575
|
+
}
|
|
1576
|
+
|
|
1577
|
+
&--select {
|
|
1578
|
+
}
|
|
1579
|
+
}
|
|
1580
|
+
}
|
|
1581
|
+
|
|
1582
|
+
&-data-row {
|
|
1583
|
+
}
|
|
1584
|
+
|
|
1585
|
+
&__cell {
|
|
1586
|
+
&--select {
|
|
1587
|
+
}
|
|
1588
|
+
|
|
1589
|
+
&--actions {
|
|
1590
|
+
white-space: nowrap;
|
|
1591
|
+
> *:not(:first-child) {
|
|
1592
|
+
margin-left: var(--actions-spacing);
|
|
1593
|
+
}
|
|
1594
|
+
}
|
|
1595
|
+
}
|
|
1596
|
+
|
|
1597
|
+
&-check,
|
|
1598
|
+
&-radio {
|
|
1599
|
+
&__label {
|
|
1600
|
+
cursor: pointer;
|
|
1601
|
+
display: inline-block;
|
|
1602
|
+
transform: translateY(2px);
|
|
1603
|
+
user-select: none;
|
|
1604
|
+
|
|
1605
|
+
&.bb-table {
|
|
1606
|
+
&-check,
|
|
1607
|
+
&-radio {
|
|
1608
|
+
&__label--disabled {
|
|
1609
|
+
cursor: default;
|
|
1610
|
+
visibility: hidden;
|
|
1611
|
+
}
|
|
1612
|
+
}
|
|
1613
|
+
}
|
|
1614
|
+
|
|
1615
|
+
&.bb-table-radio__label--disabled {
|
|
1616
|
+
cursor: default;
|
|
1617
|
+
}
|
|
1618
|
+
|
|
1619
|
+
&-text {
|
|
1620
|
+
}
|
|
1621
|
+
}
|
|
1622
|
+
}
|
|
1623
|
+
}
|
|
1624
|
+
```
|