@thangdevalone/meet-layout-grid-core 1.0.9 → 1.1.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.d.cts CHANGED
@@ -14,12 +14,11 @@ interface Position {
14
14
  }
15
15
  /**
16
16
  * Layout modes for the grid
17
- * - gallery: Equal-sized tiles in a responsive grid
18
- * - speaker: Active speaker takes larger space (2x size)
17
+ * - gallery: Equal-sized tiles in a responsive grid (use pinnedIndex for pin mode)
19
18
  * - spotlight: Single participant in focus, others hidden
20
- * - sidebar: Main view with thumbnail strip on the side
19
+ * - sidebar: Main view with thumbnail strip on the side (use sidebarPosition for top/bottom/left/right)
21
20
  */
22
- type LayoutMode = 'gallery' | 'speaker' | 'spotlight' | 'sidebar';
21
+ type LayoutMode = 'gallery' | 'spotlight' | 'sidebar';
23
22
  /**
24
23
  * Options for creating a basic grid
25
24
  */
@@ -33,16 +32,40 @@ interface GridOptions {
33
32
  /** Gap between items in pixels */
34
33
  gap: number;
35
34
  }
35
+ /**
36
+ * Aspect ratio configuration for individual items
37
+ * - string: Custom ratio like "16:9", "9:16", "4:3", "1:1"
38
+ * - 'fill': Stretch to fill the entire cell (useful for whiteboard)
39
+ * - 'auto': Use actual content dimensions (requires callback)
40
+ */
41
+ type ItemAspectRatio = string | 'fill' | 'auto';
42
+ /**
43
+ * Flex layout item info for variable-sized cells
44
+ */
45
+ interface FlexItemInfo {
46
+ /** Item index */
47
+ index: number;
48
+ /** Width of this item's cell */
49
+ width: number;
50
+ /** Height of this item's cell */
51
+ height: number;
52
+ /** Left position */
53
+ left: number;
54
+ /** Top position */
55
+ top: number;
56
+ /** Row this item belongs to */
57
+ row: number;
58
+ /** Width weight factor (based on aspect ratio) */
59
+ widthFactor: number;
60
+ }
36
61
  /**
37
62
  * Extended options for meet-style grid with layout modes
38
63
  */
39
64
  interface MeetGridOptions extends GridOptions {
40
65
  /** Layout mode for the grid */
41
66
  layoutMode?: LayoutMode;
42
- /** Index of pinned item (for speaker/spotlight modes) */
67
+ /** Index of pinned/focused item (main participant for spotlight/sidebar modes) */
43
68
  pinnedIndex?: number;
44
- /** Index of active speaker */
45
- speakerIndex?: number;
46
69
  /** Sidebar position (for sidebar mode) */
47
70
  sidebarPosition?: 'left' | 'right' | 'top' | 'bottom';
48
71
  /** Sidebar width ratio (0-1) */
@@ -51,10 +74,34 @@ interface MeetGridOptions extends GridOptions {
51
74
  maxItemsPerPage?: number;
52
75
  /** Current page index (0-based) for pagination */
53
76
  currentPage?: number;
54
- /** Maximum visible "others" in speaker/sidebar modes (0 = show all) */
55
- maxVisibleOthers?: number;
56
- /** Current page for "others" in speaker/sidebar modes (0-based) */
57
- currentOthersPage?: number;
77
+ /**
78
+ * Maximum visible items (0 = show all).
79
+ * - In gallery mode: limits total items displayed
80
+ * - In sidebar mode: limits "others" in the thumbnail strip (main item always visible)
81
+ * When set, shows a '+X' indicator on the last visible item.
82
+ * @default 0
83
+ */
84
+ maxVisible?: number;
85
+ /** Current page for items (0-based), used when maxVisible > 0 for pagination */
86
+ currentVisiblePage?: number;
87
+ /**
88
+ * Per-item aspect ratio configurations (index-based)
89
+ * Allows different aspect ratios per participant:
90
+ * - Use "9:16" for mobile/portrait participants
91
+ * - Use "16:9" for desktop/landscape participants
92
+ * - Use "fill" for whiteboard (full cell, no ratio constraint)
93
+ * - Use undefined to inherit from global aspectRatio
94
+ * @example
95
+ * itemAspectRatios: ["16:9", "9:16", "fill", undefined]
96
+ */
97
+ itemAspectRatios?: (ItemAspectRatio | undefined)[];
98
+ /**
99
+ * Enable flexible cell sizing based on item aspect ratios.
100
+ * When true, portrait items (9:16) get narrower cells, landscape items (16:9) get wider cells.
101
+ * Items are packed into rows intelligently.
102
+ * @default false
103
+ */
104
+ flexLayout?: boolean;
58
105
  }
59
106
  /**
60
107
  * Pagination info returned with grid result
@@ -88,13 +135,22 @@ interface GridResult {
88
135
  /** Function to get position of item at index */
89
136
  getPosition: (index: number) => Position;
90
137
  }
138
+ /**
139
+ * Content dimensions result with positioning info
140
+ */
141
+ interface ContentDimensions extends GridDimensions {
142
+ /** Offset from cell top to center the content */
143
+ offsetTop: number;
144
+ /** Offset from cell left to center the content */
145
+ offsetLeft: number;
146
+ }
91
147
  /**
92
148
  * Extended result for meet-style grid
93
149
  */
94
150
  interface MeetGridResult extends GridResult {
95
151
  /** Layout mode used */
96
152
  layoutMode: LayoutMode;
97
- /** Get item dimensions (may vary by index in some modes) */
153
+ /** Get item cell dimensions (the grid cell size, may vary by index in some modes) */
98
154
  getItemDimensions: (index: number) => GridDimensions;
99
155
  /** Check if item is the main/featured item */
100
156
  isMainItem: (index: number) => boolean;
@@ -102,6 +158,43 @@ interface MeetGridResult extends GridResult {
102
158
  pagination: PaginationInfo;
103
159
  /** Check if item should be visible on current page */
104
160
  isItemVisible: (index: number) => boolean;
161
+ /**
162
+ * Number of hidden items (for '+X more' indicator).
163
+ * When maxVisible is set and there are more participants than allowed,
164
+ * this indicates how many are hidden.
165
+ */
166
+ hiddenCount: number;
167
+ /**
168
+ * Get the last visible item index in the "others" section.
169
+ * Returns -1 if no items are visible or if there's no "others" section.
170
+ * Useful for showing '+X more' indicator on the last visible item.
171
+ */
172
+ getLastVisibleOthersIndex: () => number;
173
+ /**
174
+ * Get the actual content dimensions within a cell.
175
+ * Use this when items have different aspect ratios (e.g., phone vs desktop).
176
+ * Returns dimensions fitted within the cell while maintaining the item's aspect ratio.
177
+ *
178
+ * @param index - The item index
179
+ * @param itemRatio - The item's aspect ratio ("16:9", "9:16", "fill", or undefined for cell dimensions)
180
+ * @returns Content dimensions with offset for centering within the cell
181
+ *
182
+ * @example
183
+ * // For a mobile participant (9:16)
184
+ * const content = grid.getItemContentDimensions(0, "9:16")
185
+ *
186
+ * // For whiteboard (fill entire cell)
187
+ * const content = grid.getItemContentDimensions(1, "fill")
188
+ *
189
+ * // Apply in React:
190
+ * <div style={{
191
+ * width: content.width,
192
+ * height: content.height,
193
+ * marginTop: content.offsetTop,
194
+ * marginLeft: content.offsetLeft
195
+ * }}>
196
+ */
197
+ getItemContentDimensions: (index: number, itemRatio?: ItemAspectRatio) => ContentDimensions;
105
198
  }
106
199
  /**
107
200
  * Parses the Aspect Ratio string to actual ratio (height/width)
@@ -116,6 +209,53 @@ declare function parseAspectRatio(ratio: string): {
116
209
  widthRatio: number;
117
210
  heightRatio: number;
118
211
  };
212
+ /**
213
+ * Calculate content dimensions that fit within a cell while maintaining aspect ratio
214
+ * @param cellDimensions - The cell dimensions to fit content into
215
+ * @param itemRatio - The content's aspect ratio ("16:9", "9:16", "fill", etc.)
216
+ * @param defaultRatio - The default aspect ratio to use if itemRatio is undefined
217
+ * @returns Content dimensions with offset for centering
218
+ */
219
+ declare function calculateContentDimensions(cellDimensions: GridDimensions, itemRatio?: ItemAspectRatio, defaultRatio?: string): ContentDimensions;
220
+ /**
221
+ * Calculate flex layout with variable cell sizes.
222
+ * Each item maintains its aspect ratio.
223
+ * Items in the same row have the same height but different widths.
224
+ */
225
+ declare function calculateFlexLayout(options: {
226
+ dimensions: GridDimensions;
227
+ count: number;
228
+ aspectRatio: string;
229
+ gap: number;
230
+ itemAspectRatios?: (ItemAspectRatio | undefined)[];
231
+ preferHorizontal?: boolean;
232
+ }): FlexItemInfo[];
233
+ /**
234
+ * Calculate flex strip layout for sidebar (single row/column of items with different aspects).
235
+ * Used for sidebar modes where "others" need flexible sizing.
236
+ *
237
+ * @param options - Strip layout options
238
+ * @returns Array of items with positions and dimensions relative to strip origin
239
+ */
240
+ declare function calculateFlexStrip(options: {
241
+ /** Strip dimensions (width x height) */
242
+ dimensions: GridDimensions;
243
+ /** Number of items */
244
+ count: number;
245
+ /** Default aspect ratio */
246
+ aspectRatio: string;
247
+ /** Gap between items */
248
+ gap: number;
249
+ /** Per-item aspect ratios */
250
+ itemAspectRatios?: (ItemAspectRatio | undefined)[];
251
+ /** Direction of the strip */
252
+ direction: 'horizontal' | 'vertical';
253
+ /** Offset to add to all positions */
254
+ offset?: {
255
+ left: number;
256
+ top: number;
257
+ };
258
+ }): FlexItemInfo[];
119
259
  /**
120
260
  * Calculates grid item dimensions for items that can fit in a container.
121
261
  * Adapted from: https://stackoverflow.com/a/28268965
@@ -193,5 +333,5 @@ declare function getSpringConfig(preset?: SpringPreset): {
193
333
  type: "spring";
194
334
  };
195
335
 
196
- export { createGrid, createGridItemPositioner, createMeetGrid, getAspectRatio, getGridItemDimensions, getSpringConfig, parseAspectRatio, springPresets };
197
- export type { GridDimensions, GridOptions, GridResult, LayoutMode, MeetGridOptions, MeetGridResult, PaginationInfo, Position, SpringPreset };
336
+ export { calculateContentDimensions, calculateFlexLayout, calculateFlexStrip, createGrid, createGridItemPositioner, createMeetGrid, getAspectRatio, getGridItemDimensions, getSpringConfig, parseAspectRatio, springPresets };
337
+ export type { ContentDimensions, FlexItemInfo, GridDimensions, GridOptions, GridResult, ItemAspectRatio, LayoutMode, MeetGridOptions, MeetGridResult, PaginationInfo, Position, SpringPreset };
package/dist/index.d.mts CHANGED
@@ -14,12 +14,11 @@ interface Position {
14
14
  }
15
15
  /**
16
16
  * Layout modes for the grid
17
- * - gallery: Equal-sized tiles in a responsive grid
18
- * - speaker: Active speaker takes larger space (2x size)
17
+ * - gallery: Equal-sized tiles in a responsive grid (use pinnedIndex for pin mode)
19
18
  * - spotlight: Single participant in focus, others hidden
20
- * - sidebar: Main view with thumbnail strip on the side
19
+ * - sidebar: Main view with thumbnail strip on the side (use sidebarPosition for top/bottom/left/right)
21
20
  */
22
- type LayoutMode = 'gallery' | 'speaker' | 'spotlight' | 'sidebar';
21
+ type LayoutMode = 'gallery' | 'spotlight' | 'sidebar';
23
22
  /**
24
23
  * Options for creating a basic grid
25
24
  */
@@ -33,16 +32,40 @@ interface GridOptions {
33
32
  /** Gap between items in pixels */
34
33
  gap: number;
35
34
  }
35
+ /**
36
+ * Aspect ratio configuration for individual items
37
+ * - string: Custom ratio like "16:9", "9:16", "4:3", "1:1"
38
+ * - 'fill': Stretch to fill the entire cell (useful for whiteboard)
39
+ * - 'auto': Use actual content dimensions (requires callback)
40
+ */
41
+ type ItemAspectRatio = string | 'fill' | 'auto';
42
+ /**
43
+ * Flex layout item info for variable-sized cells
44
+ */
45
+ interface FlexItemInfo {
46
+ /** Item index */
47
+ index: number;
48
+ /** Width of this item's cell */
49
+ width: number;
50
+ /** Height of this item's cell */
51
+ height: number;
52
+ /** Left position */
53
+ left: number;
54
+ /** Top position */
55
+ top: number;
56
+ /** Row this item belongs to */
57
+ row: number;
58
+ /** Width weight factor (based on aspect ratio) */
59
+ widthFactor: number;
60
+ }
36
61
  /**
37
62
  * Extended options for meet-style grid with layout modes
38
63
  */
39
64
  interface MeetGridOptions extends GridOptions {
40
65
  /** Layout mode for the grid */
41
66
  layoutMode?: LayoutMode;
42
- /** Index of pinned item (for speaker/spotlight modes) */
67
+ /** Index of pinned/focused item (main participant for spotlight/sidebar modes) */
43
68
  pinnedIndex?: number;
44
- /** Index of active speaker */
45
- speakerIndex?: number;
46
69
  /** Sidebar position (for sidebar mode) */
47
70
  sidebarPosition?: 'left' | 'right' | 'top' | 'bottom';
48
71
  /** Sidebar width ratio (0-1) */
@@ -51,10 +74,34 @@ interface MeetGridOptions extends GridOptions {
51
74
  maxItemsPerPage?: number;
52
75
  /** Current page index (0-based) for pagination */
53
76
  currentPage?: number;
54
- /** Maximum visible "others" in speaker/sidebar modes (0 = show all) */
55
- maxVisibleOthers?: number;
56
- /** Current page for "others" in speaker/sidebar modes (0-based) */
57
- currentOthersPage?: number;
77
+ /**
78
+ * Maximum visible items (0 = show all).
79
+ * - In gallery mode: limits total items displayed
80
+ * - In sidebar mode: limits "others" in the thumbnail strip (main item always visible)
81
+ * When set, shows a '+X' indicator on the last visible item.
82
+ * @default 0
83
+ */
84
+ maxVisible?: number;
85
+ /** Current page for items (0-based), used when maxVisible > 0 for pagination */
86
+ currentVisiblePage?: number;
87
+ /**
88
+ * Per-item aspect ratio configurations (index-based)
89
+ * Allows different aspect ratios per participant:
90
+ * - Use "9:16" for mobile/portrait participants
91
+ * - Use "16:9" for desktop/landscape participants
92
+ * - Use "fill" for whiteboard (full cell, no ratio constraint)
93
+ * - Use undefined to inherit from global aspectRatio
94
+ * @example
95
+ * itemAspectRatios: ["16:9", "9:16", "fill", undefined]
96
+ */
97
+ itemAspectRatios?: (ItemAspectRatio | undefined)[];
98
+ /**
99
+ * Enable flexible cell sizing based on item aspect ratios.
100
+ * When true, portrait items (9:16) get narrower cells, landscape items (16:9) get wider cells.
101
+ * Items are packed into rows intelligently.
102
+ * @default false
103
+ */
104
+ flexLayout?: boolean;
58
105
  }
59
106
  /**
60
107
  * Pagination info returned with grid result
@@ -88,13 +135,22 @@ interface GridResult {
88
135
  /** Function to get position of item at index */
89
136
  getPosition: (index: number) => Position;
90
137
  }
138
+ /**
139
+ * Content dimensions result with positioning info
140
+ */
141
+ interface ContentDimensions extends GridDimensions {
142
+ /** Offset from cell top to center the content */
143
+ offsetTop: number;
144
+ /** Offset from cell left to center the content */
145
+ offsetLeft: number;
146
+ }
91
147
  /**
92
148
  * Extended result for meet-style grid
93
149
  */
94
150
  interface MeetGridResult extends GridResult {
95
151
  /** Layout mode used */
96
152
  layoutMode: LayoutMode;
97
- /** Get item dimensions (may vary by index in some modes) */
153
+ /** Get item cell dimensions (the grid cell size, may vary by index in some modes) */
98
154
  getItemDimensions: (index: number) => GridDimensions;
99
155
  /** Check if item is the main/featured item */
100
156
  isMainItem: (index: number) => boolean;
@@ -102,6 +158,43 @@ interface MeetGridResult extends GridResult {
102
158
  pagination: PaginationInfo;
103
159
  /** Check if item should be visible on current page */
104
160
  isItemVisible: (index: number) => boolean;
161
+ /**
162
+ * Number of hidden items (for '+X more' indicator).
163
+ * When maxVisible is set and there are more participants than allowed,
164
+ * this indicates how many are hidden.
165
+ */
166
+ hiddenCount: number;
167
+ /**
168
+ * Get the last visible item index in the "others" section.
169
+ * Returns -1 if no items are visible or if there's no "others" section.
170
+ * Useful for showing '+X more' indicator on the last visible item.
171
+ */
172
+ getLastVisibleOthersIndex: () => number;
173
+ /**
174
+ * Get the actual content dimensions within a cell.
175
+ * Use this when items have different aspect ratios (e.g., phone vs desktop).
176
+ * Returns dimensions fitted within the cell while maintaining the item's aspect ratio.
177
+ *
178
+ * @param index - The item index
179
+ * @param itemRatio - The item's aspect ratio ("16:9", "9:16", "fill", or undefined for cell dimensions)
180
+ * @returns Content dimensions with offset for centering within the cell
181
+ *
182
+ * @example
183
+ * // For a mobile participant (9:16)
184
+ * const content = grid.getItemContentDimensions(0, "9:16")
185
+ *
186
+ * // For whiteboard (fill entire cell)
187
+ * const content = grid.getItemContentDimensions(1, "fill")
188
+ *
189
+ * // Apply in React:
190
+ * <div style={{
191
+ * width: content.width,
192
+ * height: content.height,
193
+ * marginTop: content.offsetTop,
194
+ * marginLeft: content.offsetLeft
195
+ * }}>
196
+ */
197
+ getItemContentDimensions: (index: number, itemRatio?: ItemAspectRatio) => ContentDimensions;
105
198
  }
106
199
  /**
107
200
  * Parses the Aspect Ratio string to actual ratio (height/width)
@@ -116,6 +209,53 @@ declare function parseAspectRatio(ratio: string): {
116
209
  widthRatio: number;
117
210
  heightRatio: number;
118
211
  };
212
+ /**
213
+ * Calculate content dimensions that fit within a cell while maintaining aspect ratio
214
+ * @param cellDimensions - The cell dimensions to fit content into
215
+ * @param itemRatio - The content's aspect ratio ("16:9", "9:16", "fill", etc.)
216
+ * @param defaultRatio - The default aspect ratio to use if itemRatio is undefined
217
+ * @returns Content dimensions with offset for centering
218
+ */
219
+ declare function calculateContentDimensions(cellDimensions: GridDimensions, itemRatio?: ItemAspectRatio, defaultRatio?: string): ContentDimensions;
220
+ /**
221
+ * Calculate flex layout with variable cell sizes.
222
+ * Each item maintains its aspect ratio.
223
+ * Items in the same row have the same height but different widths.
224
+ */
225
+ declare function calculateFlexLayout(options: {
226
+ dimensions: GridDimensions;
227
+ count: number;
228
+ aspectRatio: string;
229
+ gap: number;
230
+ itemAspectRatios?: (ItemAspectRatio | undefined)[];
231
+ preferHorizontal?: boolean;
232
+ }): FlexItemInfo[];
233
+ /**
234
+ * Calculate flex strip layout for sidebar (single row/column of items with different aspects).
235
+ * Used for sidebar modes where "others" need flexible sizing.
236
+ *
237
+ * @param options - Strip layout options
238
+ * @returns Array of items with positions and dimensions relative to strip origin
239
+ */
240
+ declare function calculateFlexStrip(options: {
241
+ /** Strip dimensions (width x height) */
242
+ dimensions: GridDimensions;
243
+ /** Number of items */
244
+ count: number;
245
+ /** Default aspect ratio */
246
+ aspectRatio: string;
247
+ /** Gap between items */
248
+ gap: number;
249
+ /** Per-item aspect ratios */
250
+ itemAspectRatios?: (ItemAspectRatio | undefined)[];
251
+ /** Direction of the strip */
252
+ direction: 'horizontal' | 'vertical';
253
+ /** Offset to add to all positions */
254
+ offset?: {
255
+ left: number;
256
+ top: number;
257
+ };
258
+ }): FlexItemInfo[];
119
259
  /**
120
260
  * Calculates grid item dimensions for items that can fit in a container.
121
261
  * Adapted from: https://stackoverflow.com/a/28268965
@@ -193,5 +333,5 @@ declare function getSpringConfig(preset?: SpringPreset): {
193
333
  type: "spring";
194
334
  };
195
335
 
196
- export { createGrid, createGridItemPositioner, createMeetGrid, getAspectRatio, getGridItemDimensions, getSpringConfig, parseAspectRatio, springPresets };
197
- export type { GridDimensions, GridOptions, GridResult, LayoutMode, MeetGridOptions, MeetGridResult, PaginationInfo, Position, SpringPreset };
336
+ export { calculateContentDimensions, calculateFlexLayout, calculateFlexStrip, createGrid, createGridItemPositioner, createMeetGrid, getAspectRatio, getGridItemDimensions, getSpringConfig, parseAspectRatio, springPresets };
337
+ export type { ContentDimensions, FlexItemInfo, GridDimensions, GridOptions, GridResult, ItemAspectRatio, LayoutMode, MeetGridOptions, MeetGridResult, PaginationInfo, Position, SpringPreset };
package/dist/index.d.ts CHANGED
@@ -14,12 +14,11 @@ interface Position {
14
14
  }
15
15
  /**
16
16
  * Layout modes for the grid
17
- * - gallery: Equal-sized tiles in a responsive grid
18
- * - speaker: Active speaker takes larger space (2x size)
17
+ * - gallery: Equal-sized tiles in a responsive grid (use pinnedIndex for pin mode)
19
18
  * - spotlight: Single participant in focus, others hidden
20
- * - sidebar: Main view with thumbnail strip on the side
19
+ * - sidebar: Main view with thumbnail strip on the side (use sidebarPosition for top/bottom/left/right)
21
20
  */
22
- type LayoutMode = 'gallery' | 'speaker' | 'spotlight' | 'sidebar';
21
+ type LayoutMode = 'gallery' | 'spotlight' | 'sidebar';
23
22
  /**
24
23
  * Options for creating a basic grid
25
24
  */
@@ -33,16 +32,40 @@ interface GridOptions {
33
32
  /** Gap between items in pixels */
34
33
  gap: number;
35
34
  }
35
+ /**
36
+ * Aspect ratio configuration for individual items
37
+ * - string: Custom ratio like "16:9", "9:16", "4:3", "1:1"
38
+ * - 'fill': Stretch to fill the entire cell (useful for whiteboard)
39
+ * - 'auto': Use actual content dimensions (requires callback)
40
+ */
41
+ type ItemAspectRatio = string | 'fill' | 'auto';
42
+ /**
43
+ * Flex layout item info for variable-sized cells
44
+ */
45
+ interface FlexItemInfo {
46
+ /** Item index */
47
+ index: number;
48
+ /** Width of this item's cell */
49
+ width: number;
50
+ /** Height of this item's cell */
51
+ height: number;
52
+ /** Left position */
53
+ left: number;
54
+ /** Top position */
55
+ top: number;
56
+ /** Row this item belongs to */
57
+ row: number;
58
+ /** Width weight factor (based on aspect ratio) */
59
+ widthFactor: number;
60
+ }
36
61
  /**
37
62
  * Extended options for meet-style grid with layout modes
38
63
  */
39
64
  interface MeetGridOptions extends GridOptions {
40
65
  /** Layout mode for the grid */
41
66
  layoutMode?: LayoutMode;
42
- /** Index of pinned item (for speaker/spotlight modes) */
67
+ /** Index of pinned/focused item (main participant for spotlight/sidebar modes) */
43
68
  pinnedIndex?: number;
44
- /** Index of active speaker */
45
- speakerIndex?: number;
46
69
  /** Sidebar position (for sidebar mode) */
47
70
  sidebarPosition?: 'left' | 'right' | 'top' | 'bottom';
48
71
  /** Sidebar width ratio (0-1) */
@@ -51,10 +74,34 @@ interface MeetGridOptions extends GridOptions {
51
74
  maxItemsPerPage?: number;
52
75
  /** Current page index (0-based) for pagination */
53
76
  currentPage?: number;
54
- /** Maximum visible "others" in speaker/sidebar modes (0 = show all) */
55
- maxVisibleOthers?: number;
56
- /** Current page for "others" in speaker/sidebar modes (0-based) */
57
- currentOthersPage?: number;
77
+ /**
78
+ * Maximum visible items (0 = show all).
79
+ * - In gallery mode: limits total items displayed
80
+ * - In sidebar mode: limits "others" in the thumbnail strip (main item always visible)
81
+ * When set, shows a '+X' indicator on the last visible item.
82
+ * @default 0
83
+ */
84
+ maxVisible?: number;
85
+ /** Current page for items (0-based), used when maxVisible > 0 for pagination */
86
+ currentVisiblePage?: number;
87
+ /**
88
+ * Per-item aspect ratio configurations (index-based)
89
+ * Allows different aspect ratios per participant:
90
+ * - Use "9:16" for mobile/portrait participants
91
+ * - Use "16:9" for desktop/landscape participants
92
+ * - Use "fill" for whiteboard (full cell, no ratio constraint)
93
+ * - Use undefined to inherit from global aspectRatio
94
+ * @example
95
+ * itemAspectRatios: ["16:9", "9:16", "fill", undefined]
96
+ */
97
+ itemAspectRatios?: (ItemAspectRatio | undefined)[];
98
+ /**
99
+ * Enable flexible cell sizing based on item aspect ratios.
100
+ * When true, portrait items (9:16) get narrower cells, landscape items (16:9) get wider cells.
101
+ * Items are packed into rows intelligently.
102
+ * @default false
103
+ */
104
+ flexLayout?: boolean;
58
105
  }
59
106
  /**
60
107
  * Pagination info returned with grid result
@@ -88,13 +135,22 @@ interface GridResult {
88
135
  /** Function to get position of item at index */
89
136
  getPosition: (index: number) => Position;
90
137
  }
138
+ /**
139
+ * Content dimensions result with positioning info
140
+ */
141
+ interface ContentDimensions extends GridDimensions {
142
+ /** Offset from cell top to center the content */
143
+ offsetTop: number;
144
+ /** Offset from cell left to center the content */
145
+ offsetLeft: number;
146
+ }
91
147
  /**
92
148
  * Extended result for meet-style grid
93
149
  */
94
150
  interface MeetGridResult extends GridResult {
95
151
  /** Layout mode used */
96
152
  layoutMode: LayoutMode;
97
- /** Get item dimensions (may vary by index in some modes) */
153
+ /** Get item cell dimensions (the grid cell size, may vary by index in some modes) */
98
154
  getItemDimensions: (index: number) => GridDimensions;
99
155
  /** Check if item is the main/featured item */
100
156
  isMainItem: (index: number) => boolean;
@@ -102,6 +158,43 @@ interface MeetGridResult extends GridResult {
102
158
  pagination: PaginationInfo;
103
159
  /** Check if item should be visible on current page */
104
160
  isItemVisible: (index: number) => boolean;
161
+ /**
162
+ * Number of hidden items (for '+X more' indicator).
163
+ * When maxVisible is set and there are more participants than allowed,
164
+ * this indicates how many are hidden.
165
+ */
166
+ hiddenCount: number;
167
+ /**
168
+ * Get the last visible item index in the "others" section.
169
+ * Returns -1 if no items are visible or if there's no "others" section.
170
+ * Useful for showing '+X more' indicator on the last visible item.
171
+ */
172
+ getLastVisibleOthersIndex: () => number;
173
+ /**
174
+ * Get the actual content dimensions within a cell.
175
+ * Use this when items have different aspect ratios (e.g., phone vs desktop).
176
+ * Returns dimensions fitted within the cell while maintaining the item's aspect ratio.
177
+ *
178
+ * @param index - The item index
179
+ * @param itemRatio - The item's aspect ratio ("16:9", "9:16", "fill", or undefined for cell dimensions)
180
+ * @returns Content dimensions with offset for centering within the cell
181
+ *
182
+ * @example
183
+ * // For a mobile participant (9:16)
184
+ * const content = grid.getItemContentDimensions(0, "9:16")
185
+ *
186
+ * // For whiteboard (fill entire cell)
187
+ * const content = grid.getItemContentDimensions(1, "fill")
188
+ *
189
+ * // Apply in React:
190
+ * <div style={{
191
+ * width: content.width,
192
+ * height: content.height,
193
+ * marginTop: content.offsetTop,
194
+ * marginLeft: content.offsetLeft
195
+ * }}>
196
+ */
197
+ getItemContentDimensions: (index: number, itemRatio?: ItemAspectRatio) => ContentDimensions;
105
198
  }
106
199
  /**
107
200
  * Parses the Aspect Ratio string to actual ratio (height/width)
@@ -116,6 +209,53 @@ declare function parseAspectRatio(ratio: string): {
116
209
  widthRatio: number;
117
210
  heightRatio: number;
118
211
  };
212
+ /**
213
+ * Calculate content dimensions that fit within a cell while maintaining aspect ratio
214
+ * @param cellDimensions - The cell dimensions to fit content into
215
+ * @param itemRatio - The content's aspect ratio ("16:9", "9:16", "fill", etc.)
216
+ * @param defaultRatio - The default aspect ratio to use if itemRatio is undefined
217
+ * @returns Content dimensions with offset for centering
218
+ */
219
+ declare function calculateContentDimensions(cellDimensions: GridDimensions, itemRatio?: ItemAspectRatio, defaultRatio?: string): ContentDimensions;
220
+ /**
221
+ * Calculate flex layout with variable cell sizes.
222
+ * Each item maintains its aspect ratio.
223
+ * Items in the same row have the same height but different widths.
224
+ */
225
+ declare function calculateFlexLayout(options: {
226
+ dimensions: GridDimensions;
227
+ count: number;
228
+ aspectRatio: string;
229
+ gap: number;
230
+ itemAspectRatios?: (ItemAspectRatio | undefined)[];
231
+ preferHorizontal?: boolean;
232
+ }): FlexItemInfo[];
233
+ /**
234
+ * Calculate flex strip layout for sidebar (single row/column of items with different aspects).
235
+ * Used for sidebar modes where "others" need flexible sizing.
236
+ *
237
+ * @param options - Strip layout options
238
+ * @returns Array of items with positions and dimensions relative to strip origin
239
+ */
240
+ declare function calculateFlexStrip(options: {
241
+ /** Strip dimensions (width x height) */
242
+ dimensions: GridDimensions;
243
+ /** Number of items */
244
+ count: number;
245
+ /** Default aspect ratio */
246
+ aspectRatio: string;
247
+ /** Gap between items */
248
+ gap: number;
249
+ /** Per-item aspect ratios */
250
+ itemAspectRatios?: (ItemAspectRatio | undefined)[];
251
+ /** Direction of the strip */
252
+ direction: 'horizontal' | 'vertical';
253
+ /** Offset to add to all positions */
254
+ offset?: {
255
+ left: number;
256
+ top: number;
257
+ };
258
+ }): FlexItemInfo[];
119
259
  /**
120
260
  * Calculates grid item dimensions for items that can fit in a container.
121
261
  * Adapted from: https://stackoverflow.com/a/28268965
@@ -193,5 +333,5 @@ declare function getSpringConfig(preset?: SpringPreset): {
193
333
  type: "spring";
194
334
  };
195
335
 
196
- export { createGrid, createGridItemPositioner, createMeetGrid, getAspectRatio, getGridItemDimensions, getSpringConfig, parseAspectRatio, springPresets };
197
- export type { GridDimensions, GridOptions, GridResult, LayoutMode, MeetGridOptions, MeetGridResult, PaginationInfo, Position, SpringPreset };
336
+ export { calculateContentDimensions, calculateFlexLayout, calculateFlexStrip, createGrid, createGridItemPositioner, createMeetGrid, getAspectRatio, getGridItemDimensions, getSpringConfig, parseAspectRatio, springPresets };
337
+ export type { ContentDimensions, FlexItemInfo, GridDimensions, GridOptions, GridResult, ItemAspectRatio, LayoutMode, MeetGridOptions, MeetGridResult, PaginationInfo, Position, SpringPreset };