bitboss-ui 2.1.131 → 2.1.133

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.
Files changed (198) hide show
  1. package/dist/ai/BbDropdown.md +66 -13
  2. package/dist/ai/BbDropdownButton.md +29 -13
  3. package/dist/ai/BbTable.md +25 -11
  4. package/dist/components/BbDropdown/types.d.ts +14 -2
  5. package/dist/components/BbDropdownButton/types.d.ts +2 -2
  6. package/dist/components/BbTable/types.d.ts +6 -4
  7. package/dist/index.css +1 -1
  8. package/dist/index109.js +9 -9
  9. package/dist/index110.js +18 -18
  10. package/dist/index118.js +1 -1
  11. package/dist/index124.js +3 -3
  12. package/dist/index126.js +183 -180
  13. package/dist/index134.js +1 -1
  14. package/dist/index136.js +4 -4
  15. package/dist/index138.js +1 -1
  16. package/dist/index14.js +1 -1
  17. package/dist/index142.js +2 -2
  18. package/dist/index146.js +1 -1
  19. package/dist/index150.js +1 -1
  20. package/dist/index151.js +2 -2
  21. package/dist/index16.js +3 -3
  22. package/dist/index18.js +3 -3
  23. package/dist/index20.js +9 -9
  24. package/dist/index22.js +14 -14
  25. package/dist/index224.js +2 -2
  26. package/dist/index226.js +2 -2
  27. package/dist/index227.js +86 -5
  28. package/dist/index229.js +30 -4
  29. package/dist/index230.js +17 -13
  30. package/dist/index231.js +49 -371
  31. package/dist/index232.js +20 -0
  32. package/dist/index233.js +3 -160
  33. package/dist/index234.js +14 -0
  34. package/dist/index235.js +18 -25
  35. package/dist/index236.js +8 -2
  36. package/dist/index237.js +5 -2
  37. package/dist/index238.js +8 -2
  38. package/dist/index239.js +2 -7
  39. package/dist/index24.js +10 -10
  40. package/dist/index240.js +2 -2
  41. package/dist/index241.js +3 -7
  42. package/dist/index242.js +4 -3
  43. package/dist/index243.js +187 -33
  44. package/dist/index244.js +3 -5
  45. package/dist/index245.js +13 -5
  46. package/dist/index246.js +34 -5
  47. package/dist/index247.js +2 -5
  48. package/dist/index248.js +10 -5
  49. package/dist/index249.js +3 -5
  50. package/dist/index250.js +4 -3
  51. package/dist/index251.js +4 -8
  52. package/dist/index252.js +20 -3
  53. package/dist/index253.js +5 -18
  54. package/dist/index254.js +5 -12
  55. package/dist/index255.js +5 -51
  56. package/dist/index256.js +5 -18
  57. package/dist/index257.js +2 -12
  58. package/dist/index258.js +6 -17
  59. package/dist/index259.js +268 -30
  60. package/dist/index26.js +3 -3
  61. package/dist/index260.js +52 -18
  62. package/dist/index261.js +52 -4
  63. package/dist/index262.js +26 -100
  64. package/dist/{index297.js → index263.js} +1 -1
  65. package/dist/index264.js +5 -100
  66. package/dist/index265.js +7 -0
  67. package/dist/index266.js +5 -107
  68. package/dist/index267.js +3 -13
  69. package/dist/index268.js +160 -11
  70. package/dist/index270.js +3 -3
  71. package/dist/index271.js +7 -3
  72. package/dist/index272.js +2 -86
  73. package/dist/index273.js +4 -0
  74. package/dist/index274.js +6 -8
  75. package/dist/index275.js +7 -23
  76. package/dist/index276.js +25 -23
  77. package/dist/index277.js +9 -13
  78. package/dist/index278.js +3 -7
  79. package/dist/index279.js +13 -9
  80. package/dist/index28.js +1 -1
  81. package/dist/index280.js +13 -5
  82. package/dist/index281.js +373 -2
  83. package/dist/index283.js +23 -3
  84. package/dist/index284.js +67 -33
  85. package/dist/index285.js +7 -26
  86. package/dist/index286.js +46 -0
  87. package/dist/index287.js +52 -8
  88. package/dist/index288.js +10 -43
  89. package/dist/index289.js +16 -51
  90. package/dist/index290.js +12 -2
  91. package/dist/index291.js +33 -5
  92. package/dist/index292.js +107 -6
  93. package/dist/index293.js +5 -267
  94. package/dist/index294.js +100 -46
  95. package/dist/index296.js +96 -28
  96. package/dist/index298.js +5 -3
  97. package/dist/index299.js +8 -20
  98. package/dist/index30.js +3 -3
  99. package/dist/index300.js +23 -67
  100. package/dist/index301.js +8 -6
  101. package/dist/index302.js +6 -4
  102. package/dist/index303.js +15 -19
  103. package/dist/index304.js +28 -6
  104. package/dist/index306.js +20 -3
  105. package/dist/index307.js +3 -7
  106. package/dist/index308.js +17 -3
  107. package/dist/index309.js +28 -5
  108. package/dist/index310.js +7 -2
  109. package/dist/index311.js +4 -0
  110. package/dist/index312.js +3 -6
  111. package/dist/index313.js +5 -3
  112. package/dist/index316.js +12 -121
  113. package/dist/index317.js +2 -2
  114. package/dist/index318.js +11 -10
  115. package/dist/index32.js +2 -2
  116. package/dist/index320.js +23 -12
  117. package/dist/index322.js +2 -16
  118. package/dist/index323.js +2 -2
  119. package/dist/index324.js +2 -19
  120. package/dist/index325.js +2 -2
  121. package/dist/index326.js +2 -3
  122. package/dist/index327.js +125 -3
  123. package/dist/index328.js +2 -17
  124. package/dist/index329.js +14 -27
  125. package/dist/index330.js +2 -3
  126. package/dist/index331.js +19 -3
  127. package/dist/index332.js +2 -2
  128. package/dist/index333.js +3 -4
  129. package/dist/index334.js +4 -4
  130. package/dist/index335.js +2 -27
  131. package/dist/index336.js +3 -2
  132. package/dist/index337.js +4 -2
  133. package/dist/index338.js +6 -2
  134. package/dist/index339.js +3 -2
  135. package/dist/index34.js +8 -8
  136. package/dist/index340.js +3 -2
  137. package/dist/index341.js +1 -1
  138. package/dist/index343.js +6 -718
  139. package/dist/index344.js +716 -363
  140. package/dist/index345.js +366 -57
  141. package/dist/index346.js +56 -66
  142. package/dist/index347.js +3 -67
  143. package/dist/index348.js +5 -228
  144. package/dist/index349.js +6 -5
  145. package/dist/index351.js +2 -2
  146. package/dist/index352.js +3 -3
  147. package/dist/index353.js +6 -92
  148. package/dist/index354.js +17 -198
  149. package/dist/index355.js +9 -259
  150. package/dist/index356.js +14 -6
  151. package/dist/index357.js +91 -17
  152. package/dist/index358.js +227 -8
  153. package/dist/index359.js +66 -14
  154. package/dist/index36.js +4 -4
  155. package/dist/index360.js +67 -5
  156. package/dist/index361.js +22 -7
  157. package/dist/index363.js +133 -21
  158. package/dist/index364.js +202 -0
  159. package/dist/index365.js +259 -2
  160. package/dist/index366.js +1 -1
  161. package/dist/index367.js +2 -482
  162. package/dist/index368.js +468 -114
  163. package/dist/index369.js +127 -46
  164. package/dist/index370.js +44 -67
  165. package/dist/index371.js +66 -516
  166. package/dist/index372.js +515 -45
  167. package/dist/index373.js +52 -0
  168. package/dist/index38.js +21 -21
  169. package/dist/index40.js +7 -7
  170. package/dist/index42.js +2 -2
  171. package/dist/index44.js +8 -8
  172. package/dist/index46.js +6 -6
  173. package/dist/index50.js +2 -2
  174. package/dist/index54.js +1 -1
  175. package/dist/index56.js +1 -1
  176. package/dist/index58.js +2 -2
  177. package/dist/index60.js +2 -2
  178. package/dist/index62.js +5 -5
  179. package/dist/index68.js +1 -1
  180. package/dist/index74.js +4 -4
  181. package/dist/index82.js +194 -179
  182. package/dist/index84.js +49 -47
  183. package/dist/index86.js +2 -2
  184. package/dist/index88.js +3 -3
  185. package/dist/index90.js +1 -1
  186. package/dist/index93.js +3 -3
  187. package/dist/index95.js +2 -2
  188. package/dist/index97.js +5 -5
  189. package/dist/index99.js +1 -1
  190. package/dist/utilities/functions/normalizeItemGroups.d.ts +13 -0
  191. package/package.json +2 -2
  192. package/dist/index228.js +0 -10
  193. package/dist/index269.js +0 -12
  194. package/dist/index282.js +0 -190
  195. package/dist/index295.js +0 -54
  196. package/dist/index305.js +0 -18
  197. package/dist/index342.js +0 -4
  198. package/dist/index362.js +0 -136
@@ -49,13 +49,18 @@
49
49
  :placement="placement"
50
50
  ></slot>
51
51
  <template
52
- v-for="({ original, ...item }, index) in mappedItems"
52
+ v-for="({ original, isGroupStart, ...item }, index) in mappedItems"
53
53
  :key="item.key"
54
54
  >
55
+ <hr
56
+ v-if="isGroupStart && index > 0"
57
+ aria-hidden="true"
58
+ class="bb-dropdown__divider"
59
+ />
55
60
  <slot
56
61
  :disabled="item.disabled"
57
62
  :index="index"
58
- :item="items[index]"
63
+ :item="flatItems[index]"
59
64
  :name="`item:prepend`"
60
65
  :open="open"
61
66
  :placement="placement"
@@ -66,7 +71,7 @@
66
71
  class="bb-dropdown__item"
67
72
  :class="{
68
73
  'bb-dropdown__item--first': index === 0,
69
- 'bb-dropdown__item--last': index === items.length - 1,
74
+ 'bb-dropdown__item--last': index === flatItems.length - 1,
70
75
  }"
71
76
  :data-dropdown-item="true"
72
77
  v-bind="item"
@@ -91,7 +96,7 @@
91
96
  ><slot
92
97
  :disabled="item.disabled"
93
98
  :index="index"
94
- :item="items[index]"
99
+ :item="flatItems[index]"
95
100
  :name="`item:append`"
96
101
  :open="open"
97
102
  :placement="placement"
@@ -122,15 +127,19 @@ import type { ColumnName } from '@/types/ColumnName';
122
127
  import { extractDomContainer } from '@/utilities/functions/extractDomContainer';
123
128
  import { useElementSize, useIntersectionObserver } from '@vueuse/core';
124
129
  import { parseWidthString } from '@/utilities/functions/parseWidthString';
130
+ import { normalizeItemGroups } from '@/utilities/functions/normalizeItemGroups';
125
131
  import type {
126
132
  BbDropdownProps,
127
133
  BbDropdownSlots,
134
+ FlatItem,
128
135
  Item,
129
136
  MappedItem,
130
137
  DropdownTrigger,
131
138
  } from './types';
132
139
 
133
- type InferredBodySlots = ColumnName<BbDropdownProps['items'][number]['key']>;
140
+ type InferredBodySlots = ColumnName<
141
+ FlatItem<BbDropdownProps['items'][number]>['key']
142
+ >;
134
143
  defineSlots<BbDropdownSlots>();
135
144
 
136
145
  const props = withDefaults(defineProps<BbDropdownProps>(), {
@@ -208,14 +217,35 @@ const { resume, pause } = useIntersectionObserver(
208
217
  { threshold: [0, 1], immediate: false }
209
218
  );
210
219
 
220
+ /**
221
+ * Items normalized into divider-separated groups. A flat `items` array yields a
222
+ * single group; nested arrays (or loose items around them) become their own
223
+ * groups. See {@link normalizeItemGroups}.
224
+ */
225
+ const itemGroups = computed(() => normalizeItemGroups(props.items));
226
+ /** Flattened view of {@link itemGroups}; keyboard navigation and indices are flat. */
227
+ const flatItems = computed(() => itemGroups.value.flat());
228
+ /** Flat indices that begin a new group, used to render dividers between groups. */
229
+ const groupStartIndices = computed(() => {
230
+ const set = new Set<number>();
231
+ let offset = 0;
232
+ for (const group of itemGroups.value) {
233
+ set.add(offset);
234
+ offset += group.length;
235
+ }
236
+ return set;
237
+ });
238
+
211
239
  const mappedItems = computed(() => {
212
- let firstFocusableIndex: number = props.items.findIndex((el) => !el.disabled);
240
+ let firstFocusableIndex: number = flatItems.value.findIndex(
241
+ (el) => !el.disabled
242
+ );
213
243
  let lastFocusableIndex: number = findRightIndex(
214
- props.items,
244
+ flatItems.value,
215
245
  (item) => !item.disabled
216
246
  );
217
247
 
218
- return props.items.map((item, index) => {
248
+ return flatItems.value.map((item, index) => {
219
249
  const itemid = `${id}-item-${item.key}`;
220
250
  const { onClick: handler, ...rest } = item;
221
251
 
@@ -261,7 +291,7 @@ const mappedItems = computed(() => {
261
291
  event.preventDefault();
262
292
  if (index !== firstFocusableIndex) {
263
293
  const indexOfPrevious = findRightIndex(
264
- props.items,
294
+ flatItems.value,
265
295
  (item, i) => i < index && !item.disabled
266
296
  );
267
297
  const options = Array.from(
@@ -302,6 +332,7 @@ const mappedItems = computed(() => {
302
332
  key: item.key.split(/\W+/g).join('_').toLowerCase() as InferredBodySlots,
303
333
  disabled: rest.disabled || props.disabled,
304
334
  id: itemid,
335
+ isGroupStart: groupStartIndices.value.has(index),
305
336
  onClick,
306
337
  onKeydown,
307
338
  };
@@ -379,9 +410,9 @@ const onPointerUp = () => {
379
410
 
380
411
  const onKeydown = async (event: KeyboardEvent) => {
381
412
  if (props.disabled) return;
382
- const firstFocusableIndex = props.items.findIndex((el) => !el.disabled);
413
+ const firstFocusableIndex = flatItems.value.findIndex((el) => !el.disabled);
383
414
  const lastFocusableIndex = findRightIndex(
384
- props.items,
415
+ flatItems.value,
385
416
  (item) => !item.disabled
386
417
  );
387
418
 
@@ -592,6 +623,16 @@ export type Item = Omit<BaseButtonProps, 'block' | 'tag' | 'type'> & {
592
623
  'append:icon'?: IconType;
593
624
  };
594
625
 
626
+ /**
627
+ * Items accepted by the dropdown. A flat list renders a single group with no
628
+ * dividers; a nested array introduces a divider before and after the group.
629
+ * The two shapes can be mixed, e.g. `[item, item, [item, item], item]`.
630
+ */
631
+ export type Items = (Item | Item[])[];
632
+
633
+ /** Unwraps the item type out of the (possibly nested) {@link Items} shape. */
634
+ export type FlatItem<T> = T extends (infer U)[] ? U : T;
635
+
595
636
  export type MappedItem = Item & {
596
637
  /**
597
638
  * Identifier of the element among its siblings.
@@ -635,8 +676,12 @@ export type BbDropdownProps = Pick<
635
676
  * Array used to render each dropdown button.
636
677
  * They can act as `button`, as `a`, or as `router-link`
637
678
  * as they are based on the functionality provided by `BaseButton`.
679
+ *
680
+ * Pass a flat array for a single group, or nest arrays to split the items
681
+ * into divider-separated groups. The two shapes can be mixed, e.g.
682
+ * `[item, item, [item, item], item]`.
638
683
  */
639
- items: Item[];
684
+ items: Items;
640
685
  /**
641
686
  * Name of the theme to apply to the component. It creates a CSS class with the name of the theme.
642
687
  *
@@ -696,7 +741,7 @@ export type BbDropdownItemSlotProps = {
696
741
  /** The zero-based index of this item. */
697
742
  index: number;
698
743
  /** The raw item object from the `items` prop. */
699
- item: BbDropdownProps['items'][number];
744
+ item: FlatItem<BbDropdownProps['items'][number]>;
700
745
  /** Whether the dropdown panel is currently open. */
701
746
  open: boolean;
702
747
  /** The current placement of the dropdown panel. */
@@ -745,6 +790,14 @@ export type BbDropdownSlots = {
745
790
  display: inline-grid;
746
791
  grid-template-columns: 1fr;
747
792
  padding: 6px;
793
+ .bb-dropdown__divider {
794
+ /* Negative inline margins cancel the container padding so the rule
795
+ * spans the full width of the dropdown panel, edge to edge. */
796
+ border: none;
797
+ border-top: 1px solid color-mix(in srgb, var(--bb-text) 15%, transparent);
798
+ height: 0;
799
+ margin: 6px -6px;
800
+ }
748
801
  .bb-dropdown__item {
749
802
  border-radius: var(--bb-radius);
750
803
  column-gap: 6px;
@@ -85,7 +85,7 @@
85
85
  <slot name="item:prepend" v-bind="data" />
86
86
  </template>
87
87
  <!-- @vue-ignore - wrong inferred type -->
88
- <template v-for="item in mappedItems" #[item.key]="data">
88
+ <template v-for="item in flatMappedItems" #[item.key]="data">
89
89
  <slot :name="item.key" v-bind="data" />
90
90
  </template>
91
91
  <template #item:append="data">
@@ -103,6 +103,7 @@ import BbDropdown from '../BbDropdown/BbDropdown.vue';
103
103
  import { ref } from 'vue';
104
104
  import { BbIcon, BbSpinner } from '@/index';
105
105
  import { useLocale } from '@/composables/useLocale';
106
+ import type { Item } from '../BbDropdown/types';
106
107
  import type { BbDropdownButtonProps, BbDropdownButtonSlots } from './types';
107
108
 
108
109
  type Sizes = 'xs' | 'sm' | 'md' | 'lg' | 'xl';
@@ -131,23 +132,34 @@ const wrapClick =
131
132
  internalLoading.value--;
132
133
  };
133
134
 
134
- const mappedItems = computed(() =>
135
- props.items.map((el) => {
136
- if (el.onClick)
137
- return {
138
- ...el,
139
- key: el.key.split(/\W+/g).join('_').toLowerCase(),
140
- onClick: wrapClick(el.onClick),
141
- };
135
+ const transformItem = (el: Item) => {
136
+ if (el.onClick)
142
137
  return {
143
138
  ...el,
144
139
  key: el.key.split(/\W+/g).join('_').toLowerCase(),
140
+ onClick: wrapClick(el.onClick),
145
141
  };
146
- })
142
+ return {
143
+ ...el,
144
+ key: el.key.split(/\W+/g).join('_').toLowerCase(),
145
+ };
146
+ };
147
+
148
+ /**
149
+ * Items with leaf transforms applied while preserving the (possibly nested)
150
+ * group structure, so dividers passed down to `BbDropdown` are kept intact.
151
+ */
152
+ const mappedItems = computed(() =>
153
+ props.items.map((entry) =>
154
+ Array.isArray(entry) ? entry.map(transformItem) : transformItem(entry)
155
+ )
147
156
  );
148
157
 
158
+ /** Flattened view used for the main button and per-item named slots. */
159
+ const flatMappedItems = computed(() => mappedItems.value.flat());
160
+
149
161
  const mainBtn = computed(() => {
150
- const base = { ...mappedItems.value[0] };
162
+ const base = { ...flatMappedItems.value[0] };
151
163
  base.disabled = base.disabled || props.disabled;
152
164
  return base;
153
165
  });
@@ -178,7 +190,11 @@ const sizeAttributes = Object.entries<Sizes>(baseSize).reduce(
178
190
  ## Types
179
191
 
180
192
  ```ts
181
- import type { BbDropdownProps, MappedItem } from '../BbDropdown/types';
193
+ import type {
194
+ BbDropdownProps,
195
+ FlatItem,
196
+ MappedItem,
197
+ } from '../BbDropdown/types';
182
198
  import type { IconType } from '@/types/Icon';
183
199
 
184
200
  type Sizes = 'xs' | 'sm' | 'md' | 'lg' | 'xl';
@@ -269,7 +285,7 @@ export type BbDropdownButtonItemSlotProps = {
269
285
  /** The zero-based index of this item. */
270
286
  index: number;
271
287
  /** The raw item object from the `items` prop. */
272
- item: BbDropdownProps['items'][number];
288
+ item: FlatItem<BbDropdownProps['items'][number]>;
273
289
  /** Whether the dropdown panel is currently open. */
274
290
  open: boolean;
275
291
  /** The current placement of the dropdown panel. */
@@ -6,6 +6,7 @@
6
6
  <template>
7
7
  <component
8
8
  :is="containerTag"
9
+ :id="id"
9
10
  ref="containerRef"
10
11
  :aria-busy="loading"
11
12
  :aria-rowcount="hasProvidedAccessibilityData ? props.totalItems : undefined"
@@ -471,7 +472,6 @@ const props = withDefaults(defineProps<InternalProps<T>>(), {
471
472
  max: Infinity,
472
473
  multiple: true,
473
474
  modelValue: () => [],
474
- inheritColumnWidths: true,
475
475
  unselectedItems: () => [],
476
476
  });
477
477
 
@@ -529,17 +529,29 @@ const {
529
529
  : undefined,
530
530
  });
531
531
 
532
- const inheritColumnWidths = computed(() => props.inheritColumnWidths !== false);
532
+ /** Any column pinned to a parent track range — a per-column inherit signal. */
533
+ const hasSnap = computed(() => props.columns.some((c) => c.snap != null));
534
+
535
+ // Opt-in: inherit when explicitly enabled (`true`, or an ancestor id string),
536
+ // or implicitly when any column carries a `snap` — a snap only resolves against
537
+ // a parent's tracks, so asking for one is asking to inherit. An absent prop with
538
+ // no snaps does not inherit, so a plain nested table stays independent. An
539
+ // explicit `false` is authoritative and overrides the implicit snap signal.
540
+ const inheritColumnWidths = computed(
541
+ () => !!props.inheritColumnWidths || hasSnap.value
542
+ );
533
543
 
534
544
  /**
535
- * Assigned column widths (frozen or inherited) are only authoritative under
536
- * `table-layout: fixed`; in auto layout they behave like a minimum. So a table
537
- * that drives widths — explicitly `fixed`, inheriting from a parent, or with a
538
- * frozen column — uses fixed layout even when `fixed` was not set.
545
+ * Assigned column widths (frozen, snapped, or inherited) are only authoritative
546
+ * under `table-layout: fixed`; in auto layout they behave like a minimum. So a
547
+ * table that drives widths — explicitly `fixed`, inheriting from a parent, or
548
+ * with a column carrying a `width` or `snap` — uses fixed layout even when
549
+ * `fixed` was not set. (`snap` is a width definition: the parent track range.)
539
550
  */
540
551
  const fixedLayout = computed(
541
552
  () =>
542
553
  props.fixed ||
554
+ hasSnap.value ||
543
555
  props.columns.some((column) => column.width != null) ||
544
556
  (inheritColumnWidths.value && !!parentId.value)
545
557
  );
@@ -1723,10 +1735,12 @@ export type BbTableProps<Item = any> = {
1723
1735
  id?: string;
1724
1736
 
1725
1737
  /**
1726
- * Controls whether unfrozen columns inherit their width from an ancestor
1727
- * table's matching track, accounting for `select`/`actions` columns.
1728
- * - `true` (the default): inherit from the nearest ancestor table.
1729
- * - `false`: do not inherit.
1738
+ * Opt a nested table into inheriting its column widths from an ancestor
1739
+ * table's matching tracks (accounting for `select`/`actions` columns). This
1740
+ * also forces `table-layout: fixed`, so it is **off by default** — a nested
1741
+ * table renders independently unless you ask for alignment.
1742
+ * - `false` (the default): do not inherit; size independently.
1743
+ * - `true`: inherit from the nearest ancestor table.
1730
1744
  * - a table id (string): inherit from the specific ancestor in the chain with
1731
1745
  * that id rather than the immediate parent. Use this when an intermediate
1732
1746
  * table has a different column count, so the extra columns would otherwise
@@ -2129,7 +2143,7 @@ export type BbTableSlots<Item = any> = {
2129
2143
  }
2130
2144
 
2131
2145
  &--fixed {
2132
- table {
2146
+ > table {
2133
2147
  table-layout: fixed;
2134
2148
  width: 100%;
2135
2149
 
@@ -20,6 +20,14 @@ export type Item = Omit<BaseButtonProps, 'block' | 'tag' | 'type'> & {
20
20
  */
21
21
  'append:icon'?: IconType;
22
22
  };
23
+ /**
24
+ * Items accepted by the dropdown. A flat list renders a single group with no
25
+ * dividers; a nested array introduces a divider before and after the group.
26
+ * The two shapes can be mixed, e.g. `[item, item, [item, item], item]`.
27
+ */
28
+ export type Items = (Item | Item[])[];
29
+ /** Unwraps the item type out of the (possibly nested) {@link Items} shape. */
30
+ export type FlatItem<T> = T extends (infer U)[] ? U : T;
23
31
  export type MappedItem = Item & {
24
32
  /**
25
33
  * Identifier of the element among its siblings.
@@ -53,8 +61,12 @@ export type BbDropdownProps = Pick<CommonProps, 'arrowPadding' | 'disabled' | 'e
53
61
  * Array used to render each dropdown button.
54
62
  * They can act as `button`, as `a`, or as `router-link`
55
63
  * as they are based on the functionality provided by `BaseButton`.
64
+ *
65
+ * Pass a flat array for a single group, or nest arrays to split the items
66
+ * into divider-separated groups. The two shapes can be mixed, e.g.
67
+ * `[item, item, [item, item], item]`.
56
68
  */
57
- items: Item[];
69
+ items: Items;
58
70
  /**
59
71
  * Name of the theme to apply to the component. It creates a CSS class with the name of the theme.
60
72
  *
@@ -110,7 +122,7 @@ export type BbDropdownItemSlotProps = {
110
122
  /** The zero-based index of this item. */
111
123
  index: number;
112
124
  /** The raw item object from the `items` prop. */
113
- item: BbDropdownProps['items'][number];
125
+ item: FlatItem<BbDropdownProps['items'][number]>;
114
126
  /** Whether the dropdown panel is currently open. */
115
127
  open: boolean;
116
128
  /** The current placement of the dropdown panel. */
@@ -1,4 +1,4 @@
1
- import { BbDropdownProps, MappedItem } from '../BbDropdown/types';
1
+ import { BbDropdownProps, FlatItem, MappedItem } from '../BbDropdown/types';
2
2
  import { IconType } from '../../types/Icon';
3
3
  type Sizes = 'xs' | 'sm' | 'md' | 'lg' | 'xl';
4
4
  export type BbDropdownButtonProps = Pick<BbDropdownProps, 'arrowPadding' | 'disabled' | 'eager' | 'id' | 'items' | 'offset' | 'padding' | 'placement' | 'theme' | 'transitionDuration' | 'width'> & {
@@ -63,7 +63,7 @@ export type BbDropdownButtonItemSlotProps = {
63
63
  /** The zero-based index of this item. */
64
64
  index: number;
65
65
  /** The raw item object from the `items` prop. */
66
- item: BbDropdownProps['items'][number];
66
+ item: FlatItem<BbDropdownProps['items'][number]>;
67
67
  /** Whether the dropdown panel is currently open. */
68
68
  open: boolean;
69
69
  /** The current placement of the dropdown panel. */
@@ -118,10 +118,12 @@ export type BbTableProps<Item = any> = {
118
118
  */
119
119
  id?: string;
120
120
  /**
121
- * Controls whether unfrozen columns inherit their width from an ancestor
122
- * table's matching track, accounting for `select`/`actions` columns.
123
- * - `true` (the default): inherit from the nearest ancestor table.
124
- * - `false`: do not inherit.
121
+ * Opt a nested table into inheriting its column widths from an ancestor
122
+ * table's matching tracks (accounting for `select`/`actions` columns). This
123
+ * also forces `table-layout: fixed`, so it is **off by default** — a nested
124
+ * table renders independently unless you ask for alignment.
125
+ * - `false` (the default): do not inherit; size independently.
126
+ * - `true`: inherit from the nearest ancestor table.
125
127
  * - a table id (string): inherit from the specific ancestor in the chain with
126
128
  * that id rather than the immediate parent. Use this when an intermediate
127
129
  * table has a different column count, so the extra columns would otherwise