@onerjs/shared-ui-components 8.41.5 → 8.41.6

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.
@@ -31,6 +31,9 @@ export type AccordionAction = {
31
31
  } | {
32
32
  type: "MOVE_PINNED_UP";
33
33
  itemId: string;
34
+ } | {
35
+ type: "REMOVE_STALE_IDS";
36
+ activeIds: Set<string>;
34
37
  } | {
35
38
  type: "SHOW_ALL";
36
39
  } | {
@@ -62,8 +65,8 @@ export type AccordionContextValue = {
62
65
  features: AccordionFeatures;
63
66
  /** Ref for the pinned items portal container. */
64
67
  pinnedContainerRef: RefObject<HTMLDivElement>;
65
- /** Set of registered item IDs (for duplicate detection). */
66
- registeredItemIds: React.MutableRefObject<Set<string>>;
68
+ /** Map of registered item IDs to labels (for duplicate detection and section empty checks). */
69
+ registeredItemIds: Map<string, string>;
67
70
  };
68
71
  export declare const AccordionContext: import("react").Context<AccordionContextValue | undefined>;
69
72
  /**
@@ -85,9 +88,12 @@ export declare const AccordionSectionBlockContext: import("react").Context<Accor
85
88
  * Hook to create the AccordionSectionBlockContext value.
86
89
  *
87
90
  * @param props - AccordionSectionBlockProps
88
- * @returns AccordionSectionBlockContextValue
91
+ * @returns AccordionSectionBlockContextValue and isEmpty state
89
92
  */
90
- export declare function useAccordionSectionBlockContext(props: AccordionSectionBlockProps): AccordionSectionBlockContextValue;
93
+ export declare function useAccordionSectionBlockContext(props: AccordionSectionBlockProps): {
94
+ context: AccordionSectionBlockContextValue;
95
+ isEmpty: boolean;
96
+ };
91
97
  /**
92
98
  * Context to track whether we're inside an AccordionSectionItem.
93
99
  * Used to prevent nested items from being individually manageable.
@@ -109,6 +115,8 @@ export type AccordionItemState = {
109
115
  isMatch: boolean;
110
116
  /** The index of this item in the pinned list (for ordering). */
111
117
  pinnedIndex: number;
118
+ /** Whether this pinned item can be moved up (is not first in the pinned list). */
119
+ canMoveUp: boolean;
112
120
  /** Whether edit mode is active. */
113
121
  inEditMode: boolean;
114
122
  /** Callbacks to modify state. */
@@ -125,12 +133,3 @@ export type AccordionItemState = {
125
133
  * @returns AccordionItemState, or undefined if no accordion context or nested item.
126
134
  */
127
135
  export declare function useAccordionSectionItemState(props: AccordionSectionItemProps): AccordionItemState | undefined;
128
- /**
129
- * Hook to determine if a section should be hidden because it has no visible items.
130
- * This is computed during render based on the current state.
131
- *
132
- * @param sectionId - The section ID to check.
133
- * @param registeredItems - Map of item IDs to their labels in this section.
134
- * @returns Whether the section is empty (has no visible items).
135
- */
136
- export declare function useIsSectionEmpty(sectionId: string, registeredItems: Map<string, string>): boolean;
@@ -49,6 +49,14 @@ const AccordionReducer = (state, action) => {
49
49
  [newPinnedIds[index - 1], newPinnedIds[index]] = [newPinnedIds[index], newPinnedIds[index - 1]];
50
50
  return { ...state, pinnedIds: newPinnedIds };
51
51
  }
52
+ case "REMOVE_STALE_IDS": {
53
+ const pinnedIds = state.pinnedIds.filter((id) => action.activeIds.has(id));
54
+ const hiddenIds = state.hiddenIds.filter((id) => action.activeIds.has(id));
55
+ if (pinnedIds.length === state.pinnedIds.length && hiddenIds.length === state.hiddenIds.length) {
56
+ return state;
57
+ }
58
+ return { ...state, pinnedIds, hiddenIds };
59
+ }
52
60
  case "SHOW_ALL":
53
61
  return { ...state, hiddenIds: [] };
54
62
  case "HIDE_ALL_VISIBLE":
@@ -89,7 +97,7 @@ export function useAccordionContext(props) {
89
97
  }, [accordionId, hasFeatures, features.pinning, features.hiding]);
90
98
  const [state, dispatch] = useReducer(AccordionReducer, initialState);
91
99
  const pinnedContainerRef = useRef(null);
92
- const registeredItemIds = useRef(new Set());
100
+ const registeredItemIds = useRef(new Map());
93
101
  // Persist pinnedIds to localStorage when they change
94
102
  useEffect(() => {
95
103
  if (accordionId && features.pinning) {
@@ -102,6 +110,13 @@ export function useAccordionContext(props) {
102
110
  WriteToStorage(`Hidden/${accordionId}`, state.hiddenIds);
103
111
  }
104
112
  }, [accordionId, features.hiding, state.hiddenIds]);
113
+ // Clean stale IDs from localStorage on mount. Parent effects run after
114
+ // children's, so all items will have registered by the time this fires.
115
+ useEffect(() => {
116
+ if (accordionId && hasFeatures) {
117
+ dispatch({ type: "REMOVE_STALE_IDS", activeIds: new Set(registeredItemIds.current.keys()) });
118
+ }
119
+ }, [accordionId, hasFeatures]);
105
120
  // Return undefined if no accordionId or no features enabled
106
121
  if (!accordionId || !hasFeatures) {
107
122
  return undefined;
@@ -112,7 +127,7 @@ export function useAccordionContext(props) {
112
127
  dispatch,
113
128
  features,
114
129
  pinnedContainerRef,
115
- registeredItemIds,
130
+ registeredItemIds: registeredItemIds.current,
116
131
  };
117
132
  }
118
133
  export const AccordionSectionBlockContext = createContext(undefined);
@@ -120,11 +135,13 @@ export const AccordionSectionBlockContext = createContext(undefined);
120
135
  * Hook to create the AccordionSectionBlockContext value.
121
136
  *
122
137
  * @param props - AccordionSectionBlockProps
123
- * @returns AccordionSectionBlockContextValue
138
+ * @returns AccordionSectionBlockContextValue and isEmpty state
124
139
  */
125
140
  export function useAccordionSectionBlockContext(props) {
126
141
  const { sectionId } = props;
127
- return useMemo(() => ({ sectionId }), [sectionId]);
142
+ const context = useMemo(() => ({ sectionId }), [sectionId]);
143
+ const isEmpty = useIsSectionEmpty(sectionId);
144
+ return { context, isEmpty };
128
145
  }
129
146
  // ============================================================================
130
147
  // Item Depth Context (to detect nested AccordionSectionItems)
@@ -150,7 +167,7 @@ export function useAccordionSectionItemState(props) {
150
167
  if (!accordionCtx || !sectionCtx) {
151
168
  return "";
152
169
  }
153
- return `${accordionCtx.accordionId}\0${sectionCtx.sectionId}\0${itemId}`;
170
+ return `${accordionCtx.accordionId}/${sectionCtx.sectionId}/${itemId}`;
154
171
  }, [accordionCtx?.accordionId, sectionCtx?.sectionId, itemId]);
155
172
  // Debug: warn if itemId changes (should be stable)
156
173
  const prevItemIdRef = useRef(itemId);
@@ -161,23 +178,21 @@ export function useAccordionSectionItemState(props) {
161
178
  }
162
179
  prevItemIdRef.current = itemId;
163
180
  }, [itemId, sectionCtx?.sectionId]);
164
- // Debug: warn if itemUniqueId is not unique (duplicate detection)
181
+ // Register item and detect duplicates
165
182
  useEffect(() => {
166
183
  if (!accordionCtx || !itemUniqueId) {
167
184
  return;
168
185
  }
169
186
  const { registeredItemIds } = accordionCtx;
170
- if (registeredItemIds.current.has(itemUniqueId)) {
187
+ if (registeredItemIds.has(itemUniqueId)) {
171
188
  Logger.Warn(`Accordion: Duplicate uniqueId "${itemId}" detected in section "${sectionCtx?.sectionId}". ` +
172
189
  `Each item must have a unique ID within its section for pin/hide persistence to work correctly.`);
173
190
  }
174
- else {
175
- registeredItemIds.current.add(itemUniqueId);
176
- }
191
+ registeredItemIds.set(itemUniqueId, itemLabel ?? itemId);
177
192
  return () => {
178
- registeredItemIds.current.delete(itemUniqueId);
193
+ registeredItemIds.delete(itemUniqueId);
179
194
  };
180
- }, [accordionCtx, itemUniqueId, itemId, sectionCtx?.sectionId]);
195
+ }, [accordionCtx, itemUniqueId, itemId, itemLabel, sectionCtx?.sectionId]);
181
196
  // If no context, static item, or nested, return undefined
182
197
  if (!accordionCtx || staticItem) {
183
198
  return undefined;
@@ -188,6 +203,7 @@ export function useAccordionSectionItemState(props) {
188
203
  const isPinned = features.pinning && pinnedIds.includes(itemUniqueId);
189
204
  const isHidden = features.hiding && hiddenIds.includes(itemUniqueId);
190
205
  const pinnedIndex = isPinned ? pinnedIds.indexOf(itemUniqueId) : -1;
206
+ const canMoveUp = isPinned && pinnedIndex > 0;
191
207
  // Search matching
192
208
  const searchText = (itemLabel ?? itemId).toLowerCase();
193
209
  const isMatch = !features.search || !searchTerm || searchText.includes(searchTerm.toLowerCase());
@@ -198,6 +214,7 @@ export function useAccordionSectionItemState(props) {
198
214
  isHidden,
199
215
  isMatch,
200
216
  pinnedIndex,
217
+ canMoveUp,
201
218
  inEditMode: editMode,
202
219
  actions: {
203
220
  togglePinned: () => dispatch({ type: "TOGGLE_PINNED", itemId: itemUniqueId }),
@@ -206,48 +223,38 @@ export function useAccordionSectionItemState(props) {
206
223
  },
207
224
  };
208
225
  }
209
- // ============================================================================
210
- // Helper hook to check if a section is empty
211
- // ============================================================================
212
226
  /**
213
- * Hook to determine if a section should be hidden because it has no visible items.
214
- * This is computed during render based on the current state.
227
+ * Hook to determine if a section is empty (has no visible items).
228
+ * Derived from accordion state + globally registered items filtered by section prefix.
215
229
  *
216
230
  * @param sectionId - The section ID to check.
217
- * @param registeredItems - Map of item IDs to their labels in this section.
218
- * @returns Whether the section is empty (has no visible items).
231
+ * @returns Whether the section has no visible items.
219
232
  */
220
- export function useIsSectionEmpty(sectionId, registeredItems) {
233
+ function useIsSectionEmpty(sectionId) {
221
234
  const accordionCtx = useContext(AccordionContext);
222
235
  if (!accordionCtx) {
223
- return false; // No context means no filtering, section is not empty
236
+ return false;
224
237
  }
225
- const { state, features, accordionId } = accordionCtx;
238
+ const { state, features, accordionId, registeredItemIds } = accordionCtx;
226
239
  const { pinnedIds, hiddenIds, searchTerm, editMode } = state;
227
- // In edit mode, always show sections
228
240
  if (editMode) {
229
241
  return false;
230
242
  }
231
- // Check if any item in this section is visible
232
- for (const [itemId, itemLabel] of registeredItems) {
233
- const itemUniqueId = `${accordionId}\0${sectionId}\0${itemId}`;
234
- const isPinned = features.pinning && pinnedIds.includes(itemUniqueId);
235
- const isHidden = features.hiding && hiddenIds.includes(itemUniqueId);
236
- const searchText = (itemLabel ?? itemId).toLowerCase();
237
- const isMatch = !features.search || !searchTerm || searchText.includes(searchTerm.toLowerCase());
238
- // For the Pinned section, show items that are pinned and match
239
- if (sectionId === "Pinned") {
240
- if (isPinned && isMatch) {
241
- return false;
242
- }
243
+ const sectionPrefix = `${accordionId}/${sectionId}/`;
244
+ let hasItems = false;
245
+ for (const [itemId, itemLabel] of registeredItemIds) {
246
+ if (!itemId.startsWith(sectionPrefix)) {
247
+ continue;
243
248
  }
244
- else {
245
- // For regular sections, show items that are not pinned, not hidden, and match
246
- if (!isPinned && !isHidden && isMatch) {
247
- return false;
248
- }
249
+ hasItems = true;
250
+ const isPinned = features.pinning && pinnedIds.includes(itemId);
251
+ const isHidden = features.hiding && hiddenIds.includes(itemId);
252
+ const searchText = (itemLabel || itemId).toLowerCase();
253
+ const isMatch = !features.search || !searchTerm || searchText.includes(searchTerm.toLowerCase());
254
+ if (!isPinned && !isHidden && isMatch) {
255
+ return false;
249
256
  }
250
257
  }
251
- return true;
258
+ return hasItems;
252
259
  }
253
260
  //# sourceMappingURL=accordion.contexts.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"accordion.contexts.js","sourceRoot":"","sources":["../../../../../dev/sharedUiComponents/src/fluent/primitives/accordion.contexts.tsx"],"names":[],"mappings":"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","sourcesContent":["import type { RefObject } from \"react\";\nimport type { AccordionProps, AccordionSectionBlockProps, AccordionSectionItemProps } from \"./accordion\";\nimport { createContext, useContext, useEffect, useMemo, useReducer, useRef } from \"react\";\nimport { DataStorage } from \"core/Misc/dataStorage\";\nimport { Logger } from \"core/Misc/logger\";\n\n// ============================================================================\n// Storage Helpers\n// ============================================================================\n\nconst STORAGE_KEY_ROOT = \"Babylon/Accordion\";\n\nconst ReadFromStorage = <T,>(path: string, initial: T): T => {\n try {\n const stored = DataStorage.ReadString(`${STORAGE_KEY_ROOT}/${path}`, \"\");\n return stored ? JSON.parse(stored) : initial;\n } catch {\n return initial;\n }\n};\n\nconst WriteToStorage = (path: string, data: unknown): void => {\n DataStorage.WriteString(`${STORAGE_KEY_ROOT}/${path}`, JSON.stringify(data));\n};\n\n// ============================================================================\n// State Types\n// ============================================================================\n\n/**\n * Immutable state for the Accordion.\n */\nexport type AccordionState = {\n /** IDs of pinned items (persisted to localStorage). */\n pinnedIds: string[];\n /** IDs of hidden items (persisted to localStorage). */\n hiddenIds: string[];\n /** Current search/filter term. */\n searchTerm: string;\n /** Whether edit mode is active (shows pin/hide controls). */\n editMode: boolean;\n};\n\n/**\n * Actions that can be dispatched to update accordion state.\n */\nexport type AccordionAction =\n | { type: \"SET_SEARCH_TERM\"; term: string }\n | { type: \"SET_EDIT_MODE\"; enabled: boolean }\n | { type: \"TOGGLE_PINNED\"; itemId: string }\n | { type: \"TOGGLE_HIDDEN\"; itemId: string }\n | { type: \"MOVE_PINNED_UP\"; itemId: string }\n | { type: \"SHOW_ALL\" }\n | { type: \"HIDE_ALL_VISIBLE\"; visibleItemIds: string[] };\n\n/**\n * Feature flags for the Accordion (immutable after initialization).\n */\nexport type AccordionFeatures = {\n /** Whether pinning is enabled. */\n pinning: boolean;\n /** Whether hiding is enabled. */\n hiding: boolean;\n /** Whether search is enabled. */\n search: boolean;\n};\n\n// ============================================================================\n// Reducer\n// ============================================================================\n\nconst AccordionReducer = (state: AccordionState, action: AccordionAction): AccordionState => {\n switch (action.type) {\n case \"SET_SEARCH_TERM\":\n return { ...state, searchTerm: action.term };\n\n case \"SET_EDIT_MODE\":\n return { ...state, editMode: action.enabled };\n\n case \"TOGGLE_PINNED\": {\n const isPinned = state.pinnedIds.includes(action.itemId);\n return {\n ...state,\n pinnedIds: isPinned ? state.pinnedIds.filter((id) => id !== action.itemId) : [...state.pinnedIds, action.itemId],\n };\n }\n\n case \"TOGGLE_HIDDEN\": {\n const isHidden = state.hiddenIds.includes(action.itemId);\n return {\n ...state,\n hiddenIds: isHidden ? state.hiddenIds.filter((id) => id !== action.itemId) : [...state.hiddenIds, action.itemId],\n };\n }\n\n case \"MOVE_PINNED_UP\": {\n const index = state.pinnedIds.indexOf(action.itemId);\n if (index <= 0) {\n return state;\n }\n const newPinnedIds = [...state.pinnedIds];\n [newPinnedIds[index - 1], newPinnedIds[index]] = [newPinnedIds[index], newPinnedIds[index - 1]];\n return { ...state, pinnedIds: newPinnedIds };\n }\n\n case \"SHOW_ALL\":\n return { ...state, hiddenIds: [] };\n\n case \"HIDE_ALL_VISIBLE\":\n return {\n ...state,\n hiddenIds: [...new Set([...state.hiddenIds, ...action.visibleItemIds])],\n };\n\n default:\n return state;\n }\n};\n\n// ============================================================================\n// Accordion Context\n// ============================================================================\n\n/**\n * Context value for the Accordion component.\n */\nexport type AccordionContextValue = {\n /** The unique ID of the Accordion instance. */\n accordionId: string;\n /** State for the Accordion, managed via dispatch function. */\n state: AccordionState;\n /** Dispatch function to update state. */\n dispatch: React.Dispatch<AccordionAction>;\n /** Feature flags. */\n features: AccordionFeatures;\n /** Ref for the pinned items portal container. */\n pinnedContainerRef: RefObject<HTMLDivElement>;\n /** Set of registered item IDs (for duplicate detection). */\n registeredItemIds: React.MutableRefObject<Set<string>>;\n};\n\nexport const AccordionContext = createContext<AccordionContextValue | undefined>(undefined);\n\n/**\n * Hook to create and manage the AccordionContext value.\n *\n * @param props - AccordionProps\n * @returns AccordionContextValue, or undefined if no features are enabled or no uniqueId is provided.\n */\nexport function useAccordionContext(props: AccordionProps): AccordionContextValue | undefined {\n const { uniqueId: accordionId, enablePinnedItems, enableHiddenItems, enableSearchItems } = props;\n\n const features: AccordionFeatures = useMemo(\n () => ({\n pinning: enablePinnedItems ?? false,\n hiding: enableHiddenItems ?? false,\n search: enableSearchItems ?? false,\n }),\n [enablePinnedItems, enableHiddenItems, enableSearchItems]\n );\n\n const hasFeatures = features.pinning || features.hiding || features.search;\n\n // Initialize state from localStorage\n const initialState = useMemo((): AccordionState => {\n if (!accordionId || !hasFeatures) {\n return { pinnedIds: [], hiddenIds: [], searchTerm: \"\", editMode: false };\n }\n return {\n pinnedIds: features.pinning ? ReadFromStorage<string[]>(`Pinned/${accordionId}`, []) : [],\n hiddenIds: features.hiding ? ReadFromStorage<string[]>(`Hidden/${accordionId}`, []) : [],\n searchTerm: \"\",\n editMode: false,\n };\n }, [accordionId, hasFeatures, features.pinning, features.hiding]);\n\n const [state, dispatch] = useReducer(AccordionReducer, initialState);\n\n const pinnedContainerRef = useRef<HTMLDivElement>(null);\n const registeredItemIds = useRef<Set<string>>(new Set());\n\n // Persist pinnedIds to localStorage when they change\n useEffect(() => {\n if (accordionId && features.pinning) {\n WriteToStorage(`Pinned/${accordionId}`, state.pinnedIds);\n }\n }, [accordionId, features.pinning, state.pinnedIds]);\n\n // Persist hiddenIds to localStorage when they change\n useEffect(() => {\n if (accordionId && features.hiding) {\n WriteToStorage(`Hidden/${accordionId}`, state.hiddenIds);\n }\n }, [accordionId, features.hiding, state.hiddenIds]);\n\n // Return undefined if no accordionId or no features enabled\n if (!accordionId || !hasFeatures) {\n return undefined;\n }\n\n return {\n accordionId,\n state,\n dispatch,\n features,\n pinnedContainerRef,\n registeredItemIds,\n };\n}\n\n// ============================================================================\n// Section Context\n// ============================================================================\n\n/**\n * Context value for an AccordionSectionBlock.\n */\nexport type AccordionSectionBlockContextValue = {\n /** The section ID. */\n sectionId: string;\n};\n\nexport const AccordionSectionBlockContext = createContext<AccordionSectionBlockContextValue | undefined>(undefined);\n\n/**\n * Hook to create the AccordionSectionBlockContext value.\n *\n * @param props - AccordionSectionBlockProps\n * @returns AccordionSectionBlockContextValue\n */\nexport function useAccordionSectionBlockContext(props: AccordionSectionBlockProps): AccordionSectionBlockContextValue {\n const { sectionId } = props;\n return useMemo(() => ({ sectionId }), [sectionId]);\n}\n\n// ============================================================================\n// Item Depth Context (to detect nested AccordionSectionItems)\n// ============================================================================\n\n/**\n * Context to track whether we're inside an AccordionSectionItem.\n * Used to prevent nested items from being individually manageable.\n */\nexport const AccordionItemDepthContext = createContext<boolean>(false);\n\n// ============================================================================\n// Item Context Hook\n// ============================================================================\n\n/**\n * Derived item state, computed from the accordion state during render.\n */\nexport type AccordionItemState = {\n /** The globally unique item ID. */\n itemUniqueId: string;\n /** Whether this item is nested inside another AccordionSectionItem. */\n isNested: boolean;\n /** Whether this item is pinned. */\n isPinned: boolean;\n /** Whether this item is hidden. */\n isHidden: boolean;\n /** Whether this item matches the current search term. */\n isMatch: boolean;\n /** The index of this item in the pinned list (for ordering). */\n pinnedIndex: number;\n /** Whether edit mode is active. */\n inEditMode: boolean;\n /** Callbacks to modify state. */\n actions: {\n togglePinned: () => void;\n toggleHidden: () => void;\n movePinnedUp: () => void;\n };\n};\n\n/**\n * Hook to compute item state from accordion context.\n *\n * @param props - AccordionSectionItemProps\n * @returns AccordionItemState, or undefined if no accordion context or nested item.\n */\nexport function useAccordionSectionItemState(props: AccordionSectionItemProps): AccordionItemState | undefined {\n const { uniqueId: itemId, label: itemLabel, staticItem } = props;\n\n const accordionCtx = useContext(AccordionContext);\n const sectionCtx = useContext(AccordionSectionBlockContext);\n const isNested = useContext(AccordionItemDepthContext);\n\n // Build the globally unique item ID\n const itemUniqueId = useMemo(() => {\n if (!accordionCtx || !sectionCtx) {\n return \"\";\n }\n return `${accordionCtx.accordionId}\\0${sectionCtx.sectionId}\\0${itemId}`;\n }, [accordionCtx?.accordionId, sectionCtx?.sectionId, itemId]);\n\n // Debug: warn if itemId changes (should be stable)\n const prevItemIdRef = useRef(itemId);\n useEffect(() => {\n if (prevItemIdRef.current !== itemId) {\n Logger.Warn(\n `Accordion: The uniqueId \"${itemId}\" in section \"${sectionCtx?.sectionId}\" has changed from \"${prevItemIdRef.current}\". ` +\n `Each item must have a unique, stable ID for pin/hide persistence to work correctly.`\n );\n }\n prevItemIdRef.current = itemId;\n }, [itemId, sectionCtx?.sectionId]);\n\n // Debug: warn if itemUniqueId is not unique (duplicate detection)\n useEffect(() => {\n if (!accordionCtx || !itemUniqueId) {\n return;\n }\n const { registeredItemIds } = accordionCtx;\n if (registeredItemIds.current.has(itemUniqueId)) {\n Logger.Warn(\n `Accordion: Duplicate uniqueId \"${itemId}\" detected in section \"${sectionCtx?.sectionId}\". ` +\n `Each item must have a unique ID within its section for pin/hide persistence to work correctly.`\n );\n } else {\n registeredItemIds.current.add(itemUniqueId);\n }\n return () => {\n registeredItemIds.current.delete(itemUniqueId);\n };\n }, [accordionCtx, itemUniqueId, itemId, sectionCtx?.sectionId]);\n\n // If no context, static item, or nested, return undefined\n if (!accordionCtx || staticItem) {\n return undefined;\n }\n\n const { state, dispatch, features } = accordionCtx;\n const { pinnedIds, hiddenIds, searchTerm, editMode } = state;\n\n // Compute derived state\n const isPinned = features.pinning && pinnedIds.includes(itemUniqueId);\n const isHidden = features.hiding && hiddenIds.includes(itemUniqueId);\n const pinnedIndex = isPinned ? pinnedIds.indexOf(itemUniqueId) : -1;\n\n // Search matching\n const searchText = (itemLabel ?? itemId).toLowerCase();\n const isMatch = !features.search || !searchTerm || searchText.includes(searchTerm.toLowerCase());\n\n return {\n itemUniqueId,\n isNested,\n isPinned,\n isHidden,\n isMatch,\n pinnedIndex,\n inEditMode: editMode,\n actions: {\n togglePinned: () => dispatch({ type: \"TOGGLE_PINNED\", itemId: itemUniqueId }),\n toggleHidden: () => dispatch({ type: \"TOGGLE_HIDDEN\", itemId: itemUniqueId }),\n movePinnedUp: () => dispatch({ type: \"MOVE_PINNED_UP\", itemId: itemUniqueId }),\n },\n };\n}\n\n// ============================================================================\n// Helper hook to check if a section is empty\n// ============================================================================\n\n/**\n * Hook to determine if a section should be hidden because it has no visible items.\n * This is computed during render based on the current state.\n *\n * @param sectionId - The section ID to check.\n * @param registeredItems - Map of item IDs to their labels in this section.\n * @returns Whether the section is empty (has no visible items).\n */\nexport function useIsSectionEmpty(sectionId: string, registeredItems: Map<string, string>): boolean {\n const accordionCtx = useContext(AccordionContext);\n\n if (!accordionCtx) {\n return false; // No context means no filtering, section is not empty\n }\n\n const { state, features, accordionId } = accordionCtx;\n const { pinnedIds, hiddenIds, searchTerm, editMode } = state;\n\n // In edit mode, always show sections\n if (editMode) {\n return false;\n }\n\n // Check if any item in this section is visible\n for (const [itemId, itemLabel] of registeredItems) {\n const itemUniqueId = `${accordionId}\\0${sectionId}\\0${itemId}`;\n const isPinned = features.pinning && pinnedIds.includes(itemUniqueId);\n const isHidden = features.hiding && hiddenIds.includes(itemUniqueId);\n const searchText = (itemLabel ?? itemId).toLowerCase();\n const isMatch = !features.search || !searchTerm || searchText.includes(searchTerm.toLowerCase());\n\n // For the Pinned section, show items that are pinned and match\n if (sectionId === \"Pinned\") {\n if (isPinned && isMatch) {\n return false;\n }\n } else {\n // For regular sections, show items that are not pinned, not hidden, and match\n if (!isPinned && !isHidden && isMatch) {\n return false;\n }\n }\n }\n\n return true;\n}\n"]}
1
+ {"version":3,"file":"accordion.contexts.js","sourceRoot":"","sources":["../../../../../dev/sharedUiComponents/src/fluent/primitives/accordion.contexts.tsx"],"names":[],"mappings":"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","sourcesContent":["import type { RefObject } from \"react\";\nimport type { AccordionProps, AccordionSectionBlockProps, AccordionSectionItemProps } from \"./accordion\";\nimport { createContext, useContext, useEffect, useMemo, useReducer, useRef } from \"react\";\nimport { DataStorage } from \"core/Misc/dataStorage\";\nimport { Logger } from \"core/Misc/logger\";\n\n// ============================================================================\n// Storage Helpers\n// ============================================================================\n\nconst STORAGE_KEY_ROOT = \"Babylon/Accordion\";\n\nconst ReadFromStorage = <T,>(path: string, initial: T): T => {\n try {\n const stored = DataStorage.ReadString(`${STORAGE_KEY_ROOT}/${path}`, \"\");\n return stored ? JSON.parse(stored) : initial;\n } catch {\n return initial;\n }\n};\n\nconst WriteToStorage = (path: string, data: unknown): void => {\n DataStorage.WriteString(`${STORAGE_KEY_ROOT}/${path}`, JSON.stringify(data));\n};\n\n// ============================================================================\n// State Types\n// ============================================================================\n\n/**\n * Immutable state for the Accordion.\n */\nexport type AccordionState = {\n /** IDs of pinned items (persisted to localStorage). */\n pinnedIds: string[];\n /** IDs of hidden items (persisted to localStorage). */\n hiddenIds: string[];\n /** Current search/filter term. */\n searchTerm: string;\n /** Whether edit mode is active (shows pin/hide controls). */\n editMode: boolean;\n};\n\n/**\n * Actions that can be dispatched to update accordion state.\n */\nexport type AccordionAction =\n | { type: \"SET_SEARCH_TERM\"; term: string }\n | { type: \"SET_EDIT_MODE\"; enabled: boolean }\n | { type: \"TOGGLE_PINNED\"; itemId: string }\n | { type: \"TOGGLE_HIDDEN\"; itemId: string }\n | { type: \"MOVE_PINNED_UP\"; itemId: string }\n | { type: \"REMOVE_STALE_IDS\"; activeIds: Set<string> }\n | { type: \"SHOW_ALL\" }\n | { type: \"HIDE_ALL_VISIBLE\"; visibleItemIds: string[] };\n\n/**\n * Feature flags for the Accordion (immutable after initialization).\n */\nexport type AccordionFeatures = {\n /** Whether pinning is enabled. */\n pinning: boolean;\n /** Whether hiding is enabled. */\n hiding: boolean;\n /** Whether search is enabled. */\n search: boolean;\n};\n\n// ============================================================================\n// Reducer\n// ============================================================================\n\nconst AccordionReducer = (state: AccordionState, action: AccordionAction): AccordionState => {\n switch (action.type) {\n case \"SET_SEARCH_TERM\":\n return { ...state, searchTerm: action.term };\n\n case \"SET_EDIT_MODE\":\n return { ...state, editMode: action.enabled };\n\n case \"TOGGLE_PINNED\": {\n const isPinned = state.pinnedIds.includes(action.itemId);\n return {\n ...state,\n pinnedIds: isPinned ? state.pinnedIds.filter((id) => id !== action.itemId) : [...state.pinnedIds, action.itemId],\n };\n }\n\n case \"TOGGLE_HIDDEN\": {\n const isHidden = state.hiddenIds.includes(action.itemId);\n return {\n ...state,\n hiddenIds: isHidden ? state.hiddenIds.filter((id) => id !== action.itemId) : [...state.hiddenIds, action.itemId],\n };\n }\n\n case \"MOVE_PINNED_UP\": {\n const index = state.pinnedIds.indexOf(action.itemId);\n if (index <= 0) {\n return state;\n }\n const newPinnedIds = [...state.pinnedIds];\n [newPinnedIds[index - 1], newPinnedIds[index]] = [newPinnedIds[index], newPinnedIds[index - 1]];\n return { ...state, pinnedIds: newPinnedIds };\n }\n\n case \"REMOVE_STALE_IDS\": {\n const pinnedIds = state.pinnedIds.filter((id) => action.activeIds.has(id));\n const hiddenIds = state.hiddenIds.filter((id) => action.activeIds.has(id));\n if (pinnedIds.length === state.pinnedIds.length && hiddenIds.length === state.hiddenIds.length) {\n return state;\n }\n return { ...state, pinnedIds, hiddenIds };\n }\n\n case \"SHOW_ALL\":\n return { ...state, hiddenIds: [] };\n\n case \"HIDE_ALL_VISIBLE\":\n return {\n ...state,\n hiddenIds: [...new Set([...state.hiddenIds, ...action.visibleItemIds])],\n };\n\n default:\n return state;\n }\n};\n\n// ============================================================================\n// Accordion Context\n// ============================================================================\n\n/**\n * Context value for the Accordion component.\n */\nexport type AccordionContextValue = {\n /** The unique ID of the Accordion instance. */\n accordionId: string;\n /** State for the Accordion, managed via dispatch function. */\n state: AccordionState;\n /** Dispatch function to update state. */\n dispatch: React.Dispatch<AccordionAction>;\n /** Feature flags. */\n features: AccordionFeatures;\n /** Ref for the pinned items portal container. */\n pinnedContainerRef: RefObject<HTMLDivElement>;\n /** Map of registered item IDs to labels (for duplicate detection and section empty checks). */\n registeredItemIds: Map<string, string>;\n};\n\nexport const AccordionContext = createContext<AccordionContextValue | undefined>(undefined);\n\n/**\n * Hook to create and manage the AccordionContext value.\n *\n * @param props - AccordionProps\n * @returns AccordionContextValue, or undefined if no features are enabled or no uniqueId is provided.\n */\nexport function useAccordionContext(props: AccordionProps): AccordionContextValue | undefined {\n const { uniqueId: accordionId, enablePinnedItems, enableHiddenItems, enableSearchItems } = props;\n\n const features: AccordionFeatures = useMemo(\n () => ({\n pinning: enablePinnedItems ?? false,\n hiding: enableHiddenItems ?? false,\n search: enableSearchItems ?? false,\n }),\n [enablePinnedItems, enableHiddenItems, enableSearchItems]\n );\n\n const hasFeatures = features.pinning || features.hiding || features.search;\n\n // Initialize state from localStorage\n const initialState = useMemo((): AccordionState => {\n if (!accordionId || !hasFeatures) {\n return { pinnedIds: [], hiddenIds: [], searchTerm: \"\", editMode: false };\n }\n return {\n pinnedIds: features.pinning ? ReadFromStorage<string[]>(`Pinned/${accordionId}`, []) : [],\n hiddenIds: features.hiding ? ReadFromStorage<string[]>(`Hidden/${accordionId}`, []) : [],\n searchTerm: \"\",\n editMode: false,\n };\n }, [accordionId, hasFeatures, features.pinning, features.hiding]);\n\n const [state, dispatch] = useReducer(AccordionReducer, initialState);\n\n const pinnedContainerRef = useRef<HTMLDivElement>(null);\n const registeredItemIds = useRef<Map<string, string>>(new Map());\n\n // Persist pinnedIds to localStorage when they change\n useEffect(() => {\n if (accordionId && features.pinning) {\n WriteToStorage(`Pinned/${accordionId}`, state.pinnedIds);\n }\n }, [accordionId, features.pinning, state.pinnedIds]);\n\n // Persist hiddenIds to localStorage when they change\n useEffect(() => {\n if (accordionId && features.hiding) {\n WriteToStorage(`Hidden/${accordionId}`, state.hiddenIds);\n }\n }, [accordionId, features.hiding, state.hiddenIds]);\n\n // Clean stale IDs from localStorage on mount. Parent effects run after\n // children's, so all items will have registered by the time this fires.\n useEffect(() => {\n if (accordionId && hasFeatures) {\n dispatch({ type: \"REMOVE_STALE_IDS\", activeIds: new Set(registeredItemIds.current.keys()) });\n }\n }, [accordionId, hasFeatures]);\n\n // Return undefined if no accordionId or no features enabled\n if (!accordionId || !hasFeatures) {\n return undefined;\n }\n\n return {\n accordionId,\n state,\n dispatch,\n features,\n pinnedContainerRef,\n registeredItemIds: registeredItemIds.current,\n };\n}\n\n// ============================================================================\n// Section Context\n// ============================================================================\n\n/**\n * Context value for an AccordionSectionBlock.\n */\nexport type AccordionSectionBlockContextValue = {\n /** The section ID. */\n sectionId: string;\n};\n\nexport const AccordionSectionBlockContext = createContext<AccordionSectionBlockContextValue | undefined>(undefined);\n\n/**\n * Hook to create the AccordionSectionBlockContext value.\n *\n * @param props - AccordionSectionBlockProps\n * @returns AccordionSectionBlockContextValue and isEmpty state\n */\nexport function useAccordionSectionBlockContext(props: AccordionSectionBlockProps): {\n context: AccordionSectionBlockContextValue;\n isEmpty: boolean;\n} {\n const { sectionId } = props;\n const context = useMemo(() => ({ sectionId }), [sectionId]);\n const isEmpty = useIsSectionEmpty(sectionId);\n\n return { context, isEmpty };\n}\n\n// ============================================================================\n// Item Depth Context (to detect nested AccordionSectionItems)\n// ============================================================================\n\n/**\n * Context to track whether we're inside an AccordionSectionItem.\n * Used to prevent nested items from being individually manageable.\n */\nexport const AccordionItemDepthContext = createContext<boolean>(false);\n\n// ============================================================================\n// Item Context Hook\n// ============================================================================\n\n/**\n * Derived item state, computed from the accordion state during render.\n */\nexport type AccordionItemState = {\n /** The globally unique item ID. */\n itemUniqueId: string;\n /** Whether this item is nested inside another AccordionSectionItem. */\n isNested: boolean;\n /** Whether this item is pinned. */\n isPinned: boolean;\n /** Whether this item is hidden. */\n isHidden: boolean;\n /** Whether this item matches the current search term. */\n isMatch: boolean;\n /** The index of this item in the pinned list (for ordering). */\n pinnedIndex: number;\n /** Whether this pinned item can be moved up (is not first in the pinned list). */\n canMoveUp: boolean;\n /** Whether edit mode is active. */\n inEditMode: boolean;\n /** Callbacks to modify state. */\n actions: {\n togglePinned: () => void;\n toggleHidden: () => void;\n movePinnedUp: () => void;\n };\n};\n\n/**\n * Hook to compute item state from accordion context.\n *\n * @param props - AccordionSectionItemProps\n * @returns AccordionItemState, or undefined if no accordion context or nested item.\n */\nexport function useAccordionSectionItemState(props: AccordionSectionItemProps): AccordionItemState | undefined {\n const { uniqueId: itemId, label: itemLabel, staticItem } = props;\n\n const accordionCtx = useContext(AccordionContext);\n const sectionCtx = useContext(AccordionSectionBlockContext);\n const isNested = useContext(AccordionItemDepthContext);\n\n // Build the globally unique item ID\n const itemUniqueId = useMemo(() => {\n if (!accordionCtx || !sectionCtx) {\n return \"\";\n }\n return `${accordionCtx.accordionId}/${sectionCtx.sectionId}/${itemId}`;\n }, [accordionCtx?.accordionId, sectionCtx?.sectionId, itemId]);\n\n // Debug: warn if itemId changes (should be stable)\n const prevItemIdRef = useRef(itemId);\n useEffect(() => {\n if (prevItemIdRef.current !== itemId) {\n Logger.Warn(\n `Accordion: The uniqueId \"${itemId}\" in section \"${sectionCtx?.sectionId}\" has changed from \"${prevItemIdRef.current}\". ` +\n `Each item must have a unique, stable ID for pin/hide persistence to work correctly.`\n );\n }\n prevItemIdRef.current = itemId;\n }, [itemId, sectionCtx?.sectionId]);\n\n // Register item and detect duplicates\n useEffect(() => {\n if (!accordionCtx || !itemUniqueId) {\n return;\n }\n const { registeredItemIds } = accordionCtx;\n if (registeredItemIds.has(itemUniqueId)) {\n Logger.Warn(\n `Accordion: Duplicate uniqueId \"${itemId}\" detected in section \"${sectionCtx?.sectionId}\". ` +\n `Each item must have a unique ID within its section for pin/hide persistence to work correctly.`\n );\n }\n registeredItemIds.set(itemUniqueId, itemLabel ?? itemId);\n return () => {\n registeredItemIds.delete(itemUniqueId);\n };\n }, [accordionCtx, itemUniqueId, itemId, itemLabel, sectionCtx?.sectionId]);\n\n // If no context, static item, or nested, return undefined\n if (!accordionCtx || staticItem) {\n return undefined;\n }\n\n const { state, dispatch, features } = accordionCtx;\n const { pinnedIds, hiddenIds, searchTerm, editMode } = state;\n\n // Compute derived state\n const isPinned = features.pinning && pinnedIds.includes(itemUniqueId);\n const isHidden = features.hiding && hiddenIds.includes(itemUniqueId);\n const pinnedIndex = isPinned ? pinnedIds.indexOf(itemUniqueId) : -1;\n\n const canMoveUp = isPinned && pinnedIndex > 0;\n\n // Search matching\n const searchText = (itemLabel ?? itemId).toLowerCase();\n const isMatch = !features.search || !searchTerm || searchText.includes(searchTerm.toLowerCase());\n\n return {\n itemUniqueId,\n isNested,\n isPinned,\n isHidden,\n isMatch,\n pinnedIndex,\n canMoveUp,\n inEditMode: editMode,\n actions: {\n togglePinned: () => dispatch({ type: \"TOGGLE_PINNED\", itemId: itemUniqueId }),\n toggleHidden: () => dispatch({ type: \"TOGGLE_HIDDEN\", itemId: itemUniqueId }),\n movePinnedUp: () => dispatch({ type: \"MOVE_PINNED_UP\", itemId: itemUniqueId }),\n },\n };\n}\n/**\n * Hook to determine if a section is empty (has no visible items).\n * Derived from accordion state + globally registered items filtered by section prefix.\n *\n * @param sectionId - The section ID to check.\n * @returns Whether the section has no visible items.\n */\nfunction useIsSectionEmpty(sectionId: string): boolean {\n const accordionCtx = useContext(AccordionContext);\n\n if (!accordionCtx) {\n return false;\n }\n\n const { state, features, accordionId, registeredItemIds } = accordionCtx;\n const { pinnedIds, hiddenIds, searchTerm, editMode } = state;\n\n if (editMode) {\n return false;\n }\n\n const sectionPrefix = `${accordionId}/${sectionId}/`;\n let hasItems = false;\n\n for (const [itemId, itemLabel] of registeredItemIds) {\n if (!itemId.startsWith(sectionPrefix)) {\n continue;\n }\n hasItems = true;\n const isPinned = features.pinning && pinnedIds.includes(itemId);\n const isHidden = features.hiding && hiddenIds.includes(itemId);\n const searchText = (itemLabel || itemId).toLowerCase();\n const isMatch = !features.search || !searchTerm || searchText.includes(searchTerm.toLowerCase());\n if (!isPinned && !isHidden && isMatch) {\n return false;\n }\n }\n\n return hasItems;\n}\n"]}
@@ -58,17 +58,20 @@ const useStyles = makeStyles({
58
58
  flexGrow: 1,
59
59
  justifyContent: "end",
60
60
  },
61
- sectionEmpty: {
62
- display: "none",
63
- },
64
61
  sectionItemContainer: {
65
62
  display: "flex",
66
63
  flexDirection: "row",
64
+ alignItems: "center",
65
+ },
66
+ sectionItemContent: {
67
+ flexGrow: 1,
68
+ minWidth: 0, // Allow content to shrink below its intrinsic width when buttons are shown
69
+ overflow: "hidden",
67
70
  },
68
71
  sectionItemButtons: {
69
72
  display: "flex",
70
73
  flexDirection: "row",
71
- alignItems: "start",
74
+ alignItems: "center",
72
75
  marginRight: tokens.spacingHorizontalXS,
73
76
  },
74
77
  pinnedContainer: {
@@ -99,11 +102,10 @@ const AccordionMenuBar = () => {
99
102
  const { state, dispatch, features } = accordionCtx;
100
103
  const { editMode } = state;
101
104
  return (_jsxs("div", { className: classes.menuBar, children: [_jsx(AccordionSearchBox, {}), _jsxs("div", { className: classes.menuBarControls, children: [features.hiding && editMode && (_jsxs(_Fragment, { children: [_jsx(Button, { title: "Show all", icon: EyeFilled, appearance: "subtle", onClick: () => dispatch({ type: "SHOW_ALL" }) }), _jsx(Button, { title: "Hide all", icon: EyeOffRegular, appearance: "subtle", onClick: () => {
102
- // Hide all visible items - we pass all non-hidden, matching items
103
- // For simplicity, we dispatch with an empty array; the actual filtering
104
- // would need to be done with knowledge of all registered items.
105
- // This is a limitation - in a full implementation, you'd track registered items.
106
- dispatch({ type: "HIDE_ALL_VISIBLE", visibleItemIds: [] });
105
+ // Hide all visible (non-hidden) items using the registered item IDs
106
+ const { registeredItemIds, state: currentState } = accordionCtx;
107
+ const visibleItemIds = Array.from(registeredItemIds.keys()).filter((id) => !currentState.hiddenIds.includes(id));
108
+ dispatch({ type: "HIDE_ALL_VISIBLE", visibleItemIds });
107
109
  } })] })), (features.pinning || features.hiding) && (_jsx(Button, { title: "Edit mode", icon: editMode ? CheckmarkFilled : EditRegular, appearance: editMode ? "primary" : "subtle", onClick: () => dispatch({ type: "SET_EDIT_MODE", enabled: !editMode }) }))] })] }));
108
110
  };
109
111
  /**
@@ -117,9 +119,9 @@ const AccordionSectionBlock = (props) => {
117
119
  AccordionSectionBlock.displayName = "AccordionSectionBlock";
118
120
  const { children, sectionId } = props;
119
121
  const accordionCtx = useContext(AccordionContext);
120
- const sectionContext = useAccordionSectionBlockContext(props);
122
+ const { context: sectionContext, isEmpty } = useAccordionSectionBlockContext(props);
121
123
  if (accordionCtx) {
122
- return (_jsx(AccordionSectionBlockContext.Provider, { value: sectionContext, children: _jsx(AccordionItem, { value: sectionId, children: children }) }));
124
+ return (_jsx(AccordionSectionBlockContext.Provider, { value: sectionContext, children: !isEmpty && _jsx(AccordionItem, { value: sectionId, children: children }) }));
123
125
  }
124
126
  return _jsx(AccordionItem, { value: sectionId, children: children });
125
127
  };
@@ -149,7 +151,7 @@ export const AccordionSectionItem = (props) => {
149
151
  return _jsx(_Fragment, { children: children });
150
152
  }
151
153
  const { pinnedContainerRef, features } = accordionCtx;
152
- const { isNested, isPinned, isHidden, isMatch, pinnedIndex, inEditMode, actions } = itemState;
154
+ const { isNested, isPinned, isHidden, isMatch, pinnedIndex, canMoveUp, inEditMode, actions } = itemState;
153
155
  // Nested items just render children (don't show controls)
154
156
  if (isNested) {
155
157
  return _jsx(_Fragment, { children: children });
@@ -160,7 +162,7 @@ export const AccordionSectionItem = (props) => {
160
162
  }
161
163
  const pinnedContainer = isPinned ? pinnedContainerRef.current : null;
162
164
  const showControls = inEditMode || ctrlMode;
163
- const itemElement = (_jsxs("div", { className: classes.sectionItemContainer, style: isPinned ? { order: pinnedIndex } : undefined, onMouseMove: () => setMouseOver(true), onMouseLeave: () => setMouseOver(false), children: [showControls && (_jsxs("div", { className: classes.sectionItemButtons, children: [features.hiding && (_jsx(Button, { title: isHidden ? "Unhide" : "Hide", icon: isHidden ? EyeOffRegular : EyeFilled, appearance: "transparent", onClick: actions.toggleHidden })), features.pinning && (_jsxs(_Fragment, { children: [_jsx(Button, { title: isPinned ? "Unpin" : "Pin", icon: isPinned ? PinFilled : PinRegular, appearance: "transparent", onClick: actions.togglePinned }), isPinned && (_jsx(Button, { title: "Move up", icon: ArrowCircleUpRegular, appearance: "transparent", disabled: pinnedIndex === 0, onClick: actions.movePinnedUp }))] }))] })), _jsx(AccordionItemDepthContext.Provider, { value: true, children: children })] }));
165
+ const itemElement = (_jsxs("div", { className: classes.sectionItemContainer, style: isPinned ? { order: pinnedIndex } : undefined, onMouseMove: () => setMouseOver(true), onMouseLeave: () => setMouseOver(false), children: [showControls && (_jsxs("div", { className: classes.sectionItemButtons, children: [features.hiding && (_jsx(Button, { title: isHidden ? "Unhide" : "Hide", icon: isHidden ? EyeOffRegular : EyeFilled, appearance: "transparent", onClick: actions.toggleHidden })), features.pinning && (_jsxs(_Fragment, { children: [_jsx(Button, { title: isPinned ? "Unpin" : "Pin", icon: isPinned ? PinFilled : PinRegular, appearance: "transparent", onClick: actions.togglePinned }), isPinned && _jsx(Button, { icon: ArrowCircleUpRegular, appearance: "transparent", disabled: !canMoveUp, onClick: actions.movePinnedUp })] }))] })), _jsx(AccordionItemDepthContext.Provider, { value: true, children: _jsx("div", { className: classes.sectionItemContent, children: children }) })] }));
164
166
  return pinnedContainer ? _jsx(Portal, { mountNode: pinnedContainer, children: itemElement }) : itemElement;
165
167
  };
166
168
  /**
@@ -1 +1 @@
1
- {"version":3,"file":"accordion.js","sourceRoot":"","sources":["../../../../../dev/sharedUiComponents/src/fluent/primitives/accordion.tsx"],"names":[],"mappings":"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","sourcesContent":["import type { AccordionPanelProps, AccordionToggleData, AccordionToggleEvent, AccordionProps as FluentAccordionProps } from \"@fluentui/react-components\";\r\nimport type { ForwardRefExoticComponent, FunctionComponent, PropsWithChildren, RefAttributes } from \"react\";\r\n\r\nimport {\r\n AccordionHeader,\r\n AccordionItem,\r\n AccordionPanel,\r\n Divider,\r\n Accordion as FluentAccordion,\r\n MessageBar,\r\n MessageBarBody,\r\n Portal,\r\n SearchBox,\r\n Subtitle2Stronger,\r\n makeStyles,\r\n tokens,\r\n} from \"@fluentui/react-components\";\r\nimport { ArrowCircleUpRegular, CheckmarkFilled, EditRegular, EyeFilled, EyeOffRegular, FilterRegular, PinFilled, PinRegular } from \"@fluentui/react-icons\";\r\nimport { Children, forwardRef, isValidElement, useCallback, useContext, useEffect, useLayoutEffect, useMemo, useRef, useState } from \"react\";\r\n\r\nimport { ToolContext } from \"../hoc/fluentToolWrapper\";\r\nimport { useKeyState } from \"../hooks/keyboardHooks\";\r\nimport {\r\n AccordionContext,\r\n AccordionItemDepthContext,\r\n AccordionSectionBlockContext,\r\n useAccordionContext,\r\n useAccordionSectionBlockContext,\r\n useAccordionSectionItemState,\r\n} from \"./accordion.contexts\";\r\nimport { Button } from \"./button\";\r\nimport { CustomTokens } from \"./utils\";\r\n\r\nconst useStyles = makeStyles({\r\n accordion: {\r\n display: \"flex\",\r\n flexDirection: \"column\",\r\n height: \"100%\",\r\n },\r\n accordionBody: {\r\n overflowX: \"hidden\",\r\n overflowY: \"auto\",\r\n paddingBottom: tokens.spacingVerticalM, // bottom padding since there is no divider at the bottom\r\n },\r\n divider: {\r\n paddingTop: CustomTokens.dividerGap,\r\n paddingBottom: CustomTokens.dividerGap,\r\n },\r\n dividerSmall: {\r\n paddingTop: CustomTokens.dividerGapSmall,\r\n paddingBottom: CustomTokens.dividerGapSmall,\r\n },\r\n panelDiv: {\r\n display: \"flex\",\r\n flexDirection: \"column\",\r\n overflow: \"hidden\",\r\n },\r\n highlightDiv: {\r\n borderRadius: tokens.borderRadiusLarge,\r\n animationDuration: \"1s\",\r\n animationTimingFunction: \"ease-in-out\",\r\n animationIterationCount: \"5\",\r\n animationFillMode: \"forwards\",\r\n animationName: {\r\n from: {\r\n boxShadow: `inset 0 0 4px ${tokens.colorTransparentBackground}`,\r\n },\r\n // eslint-disable-next-line @typescript-eslint/naming-convention\r\n \"50%\": {\r\n boxShadow: `inset 0 0 12px ${tokens.colorBrandBackground}`,\r\n },\r\n to: {\r\n boxShadow: `inset 0 0 4px ${tokens.colorTransparentBackground}`,\r\n },\r\n },\r\n },\r\n menuBar: {\r\n display: \"flex\",\r\n },\r\n menuBarControls: {\r\n display: \"flex\",\r\n flexGrow: 1,\r\n justifyContent: \"end\",\r\n },\r\n sectionEmpty: {\r\n display: \"none\",\r\n },\r\n sectionItemContainer: {\r\n display: \"flex\",\r\n flexDirection: \"row\",\r\n },\r\n sectionItemButtons: {\r\n display: \"flex\",\r\n flexDirection: \"row\",\r\n alignItems: \"start\",\r\n marginRight: tokens.spacingHorizontalXS,\r\n },\r\n pinnedContainer: {\r\n display: \"flex\",\r\n flexDirection: \"column\",\r\n },\r\n pinnedContainerEmpty: {\r\n \"&:not(:only-child)\": {\r\n display: \"none\",\r\n },\r\n },\r\n searchBox: {\r\n width: \"100%\",\r\n },\r\n});\r\n\r\n/**\r\n * Renders the menu bar and control buttons.\r\n *\r\n * @returns `div`, or `undefined` if all features are disabled.\r\n */\r\nconst AccordionMenuBar: FunctionComponent = () => {\r\n AccordionMenuBar.displayName = \"AccordionMenuBar\";\r\n const classes = useStyles();\r\n const accordionCtx = useContext(AccordionContext);\r\n\r\n if (!accordionCtx) {\r\n return null;\r\n }\r\n\r\n const { state, dispatch, features } = accordionCtx;\r\n const { editMode } = state;\r\n\r\n return (\r\n <div className={classes.menuBar}>\r\n <AccordionSearchBox />\r\n <div className={classes.menuBarControls}>\r\n {features.hiding && editMode && (\r\n <>\r\n <Button title=\"Show all\" icon={EyeFilled} appearance=\"subtle\" onClick={() => dispatch({ type: \"SHOW_ALL\" })} />\r\n <Button\r\n title=\"Hide all\"\r\n icon={EyeOffRegular}\r\n appearance=\"subtle\"\r\n onClick={() => {\r\n // Hide all visible items - we pass all non-hidden, matching items\r\n // For simplicity, we dispatch with an empty array; the actual filtering\r\n // would need to be done with knowledge of all registered items.\r\n // This is a limitation - in a full implementation, you'd track registered items.\r\n dispatch({ type: \"HIDE_ALL_VISIBLE\", visibleItemIds: [] });\r\n }}\r\n />\r\n </>\r\n )}\r\n {(features.pinning || features.hiding) && (\r\n <Button\r\n title=\"Edit mode\"\r\n icon={editMode ? CheckmarkFilled : EditRegular}\r\n appearance={editMode ? \"primary\" : \"subtle\"}\r\n onClick={() => dispatch({ type: \"SET_EDIT_MODE\", enabled: !editMode })}\r\n />\r\n )}\r\n </div>\r\n </div>\r\n );\r\n};\r\n\r\n/**\r\n * Props: `AccordionSectionBlock`.\r\n */\r\nexport type AccordionSectionBlockProps = {\r\n /** The ID of the `AccordionSectionBlock`, unique within the `Accordion` instance. */\r\n sectionId: string;\r\n};\r\n\r\n/**\r\n * Wrapper component that must encapsulate the section headers and panels.\r\n * - Stores the section ID for use in `AccordionSectionItem`.\r\n *\r\n * @param props - `AccordionSectionBlockProps`\r\n * @returns `AccordionSectionBlockContext.Provider`, or `AccordionItem` if all features are disabled.\r\n */\r\nconst AccordionSectionBlock: FunctionComponent<PropsWithChildren<AccordionSectionBlockProps>> = (props) => {\r\n AccordionSectionBlock.displayName = \"AccordionSectionBlock\";\r\n const { children, sectionId } = props;\r\n const accordionCtx = useContext(AccordionContext);\r\n const sectionContext = useAccordionSectionBlockContext(props);\r\n\r\n if (accordionCtx) {\r\n return (\r\n <AccordionSectionBlockContext.Provider value={sectionContext}>\r\n <AccordionItem value={sectionId}>{children}</AccordionItem>\r\n </AccordionSectionBlockContext.Provider>\r\n );\r\n }\r\n\r\n return <AccordionItem value={sectionId}>{children}</AccordionItem>;\r\n};\r\n\r\n/**\r\n * Props: `AccordionSectionItem`.\r\n */\r\nexport type AccordionSectionItemProps = {\r\n /** The ID of the `AccordionSectionItem`, unique within the `AccordionSectionBlock` instance. */\r\n uniqueId: string;\r\n /** The searchable text label for the item. */\r\n label?: string;\r\n /** Whether the item is not interactable. */\r\n staticItem?: boolean;\r\n};\r\n\r\n/**\r\n * Wrapper component that must encapsulate individual items.\r\n * - Renders the pin button and tracks the pinned state of the item.\r\n * - Renders the hide button and tracks the hidden state of the item.\r\n * - Filters items based on the current search term.\r\n *\r\n * @param props - `AccordionSectionItemProps`\r\n * @returns `Portal` if pinned; `null` if hidden/filtered; `children` otherwise.\r\n */\r\nexport const AccordionSectionItem: FunctionComponent<PropsWithChildren<AccordionSectionItemProps>> = (props) => {\r\n AccordionSectionItem.displayName = \"AccordionSectionItem\";\r\n const { children, staticItem } = props;\r\n const classes = useStyles();\r\n const accordionCtx = useContext(AccordionContext);\r\n const itemState = useAccordionSectionItemState(props);\r\n const [ctrlMode, setCtrlMode] = useState(false);\r\n const ctrlPressed = useKeyState(\"Control\");\r\n const [mouseOver, setMouseOver] = useState(false);\r\n\r\n useEffect(() => {\r\n setCtrlMode(ctrlPressed && mouseOver);\r\n }, [ctrlPressed, mouseOver]);\r\n\r\n // If static item or no context, just render children\r\n if (staticItem || !accordionCtx || !itemState) {\r\n return <>{children}</>;\r\n }\r\n\r\n const { pinnedContainerRef, features } = accordionCtx;\r\n const { isNested, isPinned, isHidden, isMatch, pinnedIndex, inEditMode, actions } = itemState;\r\n\r\n // Nested items just render children (don't show controls)\r\n if (isNested) {\r\n return <>{children}</>;\r\n }\r\n\r\n // If hidden (and not in edit mode) or doesn't match search, don't render\r\n if ((isHidden && !inEditMode) || !isMatch) {\r\n return null;\r\n }\r\n\r\n const pinnedContainer = isPinned ? pinnedContainerRef.current : null;\r\n const showControls = inEditMode || ctrlMode;\r\n\r\n const itemElement = (\r\n <div\r\n className={classes.sectionItemContainer}\r\n style={isPinned ? { order: pinnedIndex } : undefined}\r\n onMouseMove={() => setMouseOver(true)}\r\n onMouseLeave={() => setMouseOver(false)}\r\n >\r\n {showControls && (\r\n <div className={classes.sectionItemButtons}>\r\n {features.hiding && (\r\n <Button title={isHidden ? \"Unhide\" : \"Hide\"} icon={isHidden ? EyeOffRegular : EyeFilled} appearance=\"transparent\" onClick={actions.toggleHidden} />\r\n )}\r\n {features.pinning && (\r\n <>\r\n <Button title={isPinned ? \"Unpin\" : \"Pin\"} icon={isPinned ? PinFilled : PinRegular} appearance=\"transparent\" onClick={actions.togglePinned} />\r\n {isPinned && (\r\n <Button title=\"Move up\" icon={ArrowCircleUpRegular} appearance=\"transparent\" disabled={pinnedIndex === 0} onClick={actions.movePinnedUp} />\r\n )}\r\n </>\r\n )}\r\n </div>\r\n )}\r\n <AccordionItemDepthContext.Provider value={true}>{children}</AccordionItemDepthContext.Provider>\r\n </div>\r\n );\r\n\r\n return pinnedContainer ? <Portal mountNode={pinnedContainer}>{itemElement}</Portal> : itemElement;\r\n};\r\n\r\n/**\r\n * Renders the Pinned section container and defines the portal target for the pinned items.\r\n *\r\n * @returns `div`\r\n */\r\nconst AccordionPinnedContainer: FunctionComponent = () => {\r\n AccordionPinnedContainer.displayName = \"AccordionPinnedContainer\";\r\n const classes = useStyles();\r\n const accordionCtx = useContext(AccordionContext);\r\n\r\n return (\r\n <div ref={accordionCtx?.pinnedContainerRef} className={classes.pinnedContainer}>\r\n <MessageBar className={classes.pinnedContainerEmpty}>\r\n <MessageBarBody>No pinned items</MessageBarBody>\r\n </MessageBar>\r\n </div>\r\n );\r\n};\r\n\r\n/**\r\n * Renders the search box for filtering items.\r\n *\r\n * @returns `SearchBox`, or `null` if the feature is disabled.\r\n */\r\nconst AccordionSearchBox: FunctionComponent = () => {\r\n AccordionSearchBox.displayName = \"AccordionSearchBox\";\r\n const classes = useStyles();\r\n const accordionCtx = useContext(AccordionContext);\r\n\r\n if (!accordionCtx?.features.search) {\r\n return null;\r\n }\r\n\r\n const { state, dispatch } = accordionCtx;\r\n\r\n return (\r\n <SearchBox\r\n className={classes.searchBox}\r\n appearance=\"underline\"\r\n contentBefore={<FilterRegular />}\r\n placeholder=\"Filter\"\r\n value={state.searchTerm}\r\n onChange={(_, data) => dispatch({ type: \"SET_SEARCH_TERM\", term: data.value })}\r\n />\r\n );\r\n};\r\n\r\n/**\r\n * Props: `AccordionSection`.\r\n */\r\nexport type AccordionSectionProps = {\r\n /** The text label shown in the section header. */\r\n title: string;\r\n /** Indicates whether the `AccordionSection` is initially collapsed. */\r\n collapseByDefault?: boolean;\r\n};\r\n\r\n/**\r\n * Wrapper component that must encapsulate the section body.\r\n *\r\n * @param props - `AccordionSectionProps`\r\n * @returns `div`\r\n */\r\nexport const AccordionSection: FunctionComponent<PropsWithChildren<AccordionSectionProps>> = (props) => {\r\n AccordionSection.displayName = \"AccordionSection\";\r\n const classes = useStyles();\r\n\r\n return <div className={classes.panelDiv}>{props.children}</div>;\r\n};\r\n\r\n/**\r\n * Props: `Accordion`.\r\n */\r\nexport type AccordionProps = {\r\n /** The unique ID of the `Accordion` instance. */\r\n uniqueId?: string;\r\n /** The list of sections to be highlighted. */\r\n highlightSections?: readonly string[];\r\n /** Enables the pinned items feature. */\r\n enablePinnedItems?: boolean;\r\n /** Enables the hidden items feature. */\r\n enableHiddenItems?: boolean;\r\n /** Enables the search items feature. */\r\n enableSearchItems?: boolean;\r\n};\r\n\r\nconst StringAccordion = FluentAccordion as ForwardRefExoticComponent<FluentAccordionProps<string> & RefAttributes<HTMLDivElement>>;\r\n\r\nexport const Accordion = forwardRef<HTMLDivElement, PropsWithChildren<AccordionProps>>((props, ref) => {\r\n Accordion.displayName = \"Accordion\";\r\n const { children, highlightSections, ...rest } = props;\r\n const classes = useStyles();\r\n const { size } = useContext(ToolContext);\r\n const accordionCtx = useAccordionContext(props);\r\n const hasPinning = accordionCtx?.features.pinning ?? false;\r\n\r\n const pinnedSectionElement = useMemo(() => {\r\n return (\r\n hasPinning && (\r\n <AccordionSection title=\"Pinned\" collapseByDefault={false}>\r\n <AccordionPinnedContainer />\r\n </AccordionSection>\r\n )\r\n );\r\n }, [hasPinning]);\r\n\r\n // Prevents sections contents from unmounting when closed, allowing their elements to be used in the Pinned section.\r\n const preventUnmountMotion: AccordionPanelProps[\"collapseMotion\"] = useMemo(() => {\r\n // https://github.com/microsoft/fluentui/issues/34309#issuecomment-2824364945\r\n // eslint-disable-next-line @typescript-eslint/naming-convention\r\n return hasPinning ? { children: (Component, props) => <Component {...props} unmountOnExit={false} /> } : undefined;\r\n }, [hasPinning]);\r\n\r\n const validChildren = useMemo(() => {\r\n return (\r\n Children.map([pinnedSectionElement, children], (child) => {\r\n if (isValidElement(child)) {\r\n const childProps = child.props as Partial<AccordionSectionProps>;\r\n if (childProps.title) {\r\n return {\r\n title: childProps.title,\r\n collapseByDefault: childProps.collapseByDefault,\r\n content: child,\r\n };\r\n }\r\n }\r\n return null;\r\n })?.filter(Boolean) ?? []\r\n );\r\n }, [children]);\r\n\r\n // Tracks open items, and used to tell the Accordion which sections should be expanded.\r\n const [openItems, setOpenItems] = useState(validChildren.filter((child) => !child.collapseByDefault).map((child) => child.title));\r\n\r\n // Tracks closed items, which is needed so that when the children change, we only update the open/closed state\r\n // (depending on the collapseByDefault prop) for items that have not been explicitly opened or closed.\r\n const [closedItems, setClosedItems] = useState(validChildren.filter((child) => child.collapseByDefault).map((child) => child.title));\r\n\r\n const internalOpenItemsRef = useRef<string[] | undefined>(openItems);\r\n\r\n // When highlight sections is requested, we temporarily override the open items, but if highlight sections is cleared,\r\n // then we revert back to the normal open items tracking.\r\n useLayoutEffect(() => {\r\n if (highlightSections) {\r\n internalOpenItemsRef.current = [...openItems];\r\n setOpenItems([...highlightSections]);\r\n } else {\r\n setOpenItems([...(internalOpenItemsRef.current ?? [])]);\r\n internalOpenItemsRef.current = undefined;\r\n }\r\n }, [highlightSections]);\r\n\r\n useEffect(() => {\r\n for (const defaultOpenItem of validChildren.filter((child) => !child.collapseByDefault).map((child) => child.title)) {\r\n // If a child is not marked as collapseByDefault, then it should be opened by default, and\r\n // it is only \"default\" if it hasn't already been explicitly added to the opened or closed list.\r\n if (!closedItems.includes(defaultOpenItem) && !openItems.includes(defaultOpenItem)) {\r\n setOpenItems((prev) => [...prev, defaultOpenItem]);\r\n }\r\n }\r\n }, [validChildren]);\r\n\r\n const onToggle = useCallback((event: AccordionToggleEvent, data: AccordionToggleData<string>) => {\r\n if (data.openItems.includes(data.value)) {\r\n setOpenItems((prev) => [...prev, data.value]);\r\n setClosedItems((prev) => prev.filter((item) => item !== data.value));\r\n } else {\r\n setClosedItems((prev) => [...prev, data.value]);\r\n setOpenItems((prev) => prev.filter((item) => item !== data.value));\r\n }\r\n }, []);\r\n\r\n return (\r\n <StringAccordion ref={ref} className={classes.accordion} collapsible multiple onToggle={onToggle} openItems={openItems} {...rest}>\r\n <AccordionContext.Provider value={accordionCtx}>\r\n <AccordionMenuBar />\r\n <div className={classes.accordionBody}>\r\n {validChildren.map((child, index) => {\r\n const isHighlighted = highlightSections?.includes(child.title);\r\n return (\r\n <AccordionSectionBlock key={child.content.key ?? child.title} sectionId={child.title}>\r\n <div className={isHighlighted ? classes.highlightDiv : undefined}>\r\n <AccordionHeader size={size}>\r\n <Subtitle2Stronger>{child.title}</Subtitle2Stronger>\r\n </AccordionHeader>\r\n <AccordionPanel collapseMotion={preventUnmountMotion}>\r\n <div className={classes.panelDiv}>{child.content}</div>\r\n </AccordionPanel>\r\n </div>\r\n {index < validChildren.length - 1 && <Divider inset={true} className={size === \"small\" ? classes.dividerSmall : classes.divider} />}\r\n </AccordionSectionBlock>\r\n );\r\n })}\r\n </div>\r\n </AccordionContext.Provider>\r\n </StringAccordion>\r\n );\r\n});\r\n"]}
1
+ {"version":3,"file":"accordion.js","sourceRoot":"","sources":["../../../../../dev/sharedUiComponents/src/fluent/primitives/accordion.tsx"],"names":[],"mappings":"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","sourcesContent":["import type { AccordionPanelProps, AccordionToggleData, AccordionToggleEvent, AccordionProps as FluentAccordionProps } from \"@fluentui/react-components\";\r\nimport type { ForwardRefExoticComponent, FunctionComponent, PropsWithChildren, RefAttributes } from \"react\";\r\n\r\nimport {\r\n AccordionHeader,\r\n AccordionItem,\r\n AccordionPanel,\r\n Divider,\r\n Accordion as FluentAccordion,\r\n MessageBar,\r\n MessageBarBody,\r\n Portal,\r\n SearchBox,\r\n Subtitle2Stronger,\r\n makeStyles,\r\n tokens,\r\n} from \"@fluentui/react-components\";\r\nimport { ArrowCircleUpRegular, CheckmarkFilled, EditRegular, EyeFilled, EyeOffRegular, FilterRegular, PinFilled, PinRegular } from \"@fluentui/react-icons\";\r\nimport { Children, forwardRef, isValidElement, useCallback, useContext, useEffect, useLayoutEffect, useMemo, useRef, useState } from \"react\";\r\n\r\nimport { ToolContext } from \"../hoc/fluentToolWrapper\";\r\nimport { useKeyState } from \"../hooks/keyboardHooks\";\r\nimport {\r\n AccordionContext,\r\n AccordionItemDepthContext,\r\n AccordionSectionBlockContext,\r\n useAccordionContext,\r\n useAccordionSectionBlockContext,\r\n useAccordionSectionItemState,\r\n} from \"./accordion.contexts\";\r\nimport { Button } from \"./button\";\r\nimport { CustomTokens } from \"./utils\";\r\n\r\nconst useStyles = makeStyles({\r\n accordion: {\r\n display: \"flex\",\r\n flexDirection: \"column\",\r\n height: \"100%\",\r\n },\r\n accordionBody: {\r\n overflowX: \"hidden\",\r\n overflowY: \"auto\",\r\n paddingBottom: tokens.spacingVerticalM, // bottom padding since there is no divider at the bottom\r\n },\r\n divider: {\r\n paddingTop: CustomTokens.dividerGap,\r\n paddingBottom: CustomTokens.dividerGap,\r\n },\r\n dividerSmall: {\r\n paddingTop: CustomTokens.dividerGapSmall,\r\n paddingBottom: CustomTokens.dividerGapSmall,\r\n },\r\n panelDiv: {\r\n display: \"flex\",\r\n flexDirection: \"column\",\r\n overflow: \"hidden\",\r\n },\r\n highlightDiv: {\r\n borderRadius: tokens.borderRadiusLarge,\r\n animationDuration: \"1s\",\r\n animationTimingFunction: \"ease-in-out\",\r\n animationIterationCount: \"5\",\r\n animationFillMode: \"forwards\",\r\n animationName: {\r\n from: {\r\n boxShadow: `inset 0 0 4px ${tokens.colorTransparentBackground}`,\r\n },\r\n // eslint-disable-next-line @typescript-eslint/naming-convention\r\n \"50%\": {\r\n boxShadow: `inset 0 0 12px ${tokens.colorBrandBackground}`,\r\n },\r\n to: {\r\n boxShadow: `inset 0 0 4px ${tokens.colorTransparentBackground}`,\r\n },\r\n },\r\n },\r\n menuBar: {\r\n display: \"flex\",\r\n },\r\n menuBarControls: {\r\n display: \"flex\",\r\n flexGrow: 1,\r\n justifyContent: \"end\",\r\n },\r\n sectionItemContainer: {\r\n display: \"flex\",\r\n flexDirection: \"row\",\r\n alignItems: \"center\",\r\n },\r\n sectionItemContent: {\r\n flexGrow: 1,\r\n minWidth: 0, // Allow content to shrink below its intrinsic width when buttons are shown\r\n overflow: \"hidden\",\r\n },\r\n sectionItemButtons: {\r\n display: \"flex\",\r\n flexDirection: \"row\",\r\n alignItems: \"center\",\r\n marginRight: tokens.spacingHorizontalXS,\r\n },\r\n pinnedContainer: {\r\n display: \"flex\",\r\n flexDirection: \"column\",\r\n },\r\n pinnedContainerEmpty: {\r\n \"&:not(:only-child)\": {\r\n display: \"none\",\r\n },\r\n },\r\n searchBox: {\r\n width: \"100%\",\r\n },\r\n});\r\n\r\n/**\r\n * Renders the menu bar and control buttons.\r\n *\r\n * @returns `div`, or `undefined` if all features are disabled.\r\n */\r\nconst AccordionMenuBar: FunctionComponent = () => {\r\n AccordionMenuBar.displayName = \"AccordionMenuBar\";\r\n const classes = useStyles();\r\n const accordionCtx = useContext(AccordionContext);\r\n\r\n if (!accordionCtx) {\r\n return null;\r\n }\r\n\r\n const { state, dispatch, features } = accordionCtx;\r\n const { editMode } = state;\r\n\r\n return (\r\n <div className={classes.menuBar}>\r\n <AccordionSearchBox />\r\n <div className={classes.menuBarControls}>\r\n {features.hiding && editMode && (\r\n <>\r\n <Button title=\"Show all\" icon={EyeFilled} appearance=\"subtle\" onClick={() => dispatch({ type: \"SHOW_ALL\" })} />\r\n <Button\r\n title=\"Hide all\"\r\n icon={EyeOffRegular}\r\n appearance=\"subtle\"\r\n onClick={() => {\r\n // Hide all visible (non-hidden) items using the registered item IDs\r\n const { registeredItemIds, state: currentState } = accordionCtx;\r\n const visibleItemIds = Array.from(registeredItemIds.keys()).filter((id) => !currentState.hiddenIds.includes(id));\r\n dispatch({ type: \"HIDE_ALL_VISIBLE\", visibleItemIds });\r\n }}\r\n />\r\n </>\r\n )}\r\n {(features.pinning || features.hiding) && (\r\n <Button\r\n title=\"Edit mode\"\r\n icon={editMode ? CheckmarkFilled : EditRegular}\r\n appearance={editMode ? \"primary\" : \"subtle\"}\r\n onClick={() => dispatch({ type: \"SET_EDIT_MODE\", enabled: !editMode })}\r\n />\r\n )}\r\n </div>\r\n </div>\r\n );\r\n};\r\n\r\n/**\r\n * Props: `AccordionSectionBlock`.\r\n */\r\nexport type AccordionSectionBlockProps = {\r\n /** The ID of the `AccordionSectionBlock`, unique within the `Accordion` instance. */\r\n sectionId: string;\r\n};\r\n\r\n/**\r\n * Wrapper component that must encapsulate the section headers and panels.\r\n * - Stores the section ID for use in `AccordionSectionItem`.\r\n *\r\n * @param props - `AccordionSectionBlockProps`\r\n * @returns `AccordionSectionBlockContext.Provider`, or `AccordionItem` if all features are disabled.\r\n */\r\nconst AccordionSectionBlock: FunctionComponent<PropsWithChildren<AccordionSectionBlockProps>> = (props) => {\r\n AccordionSectionBlock.displayName = \"AccordionSectionBlock\";\r\n const { children, sectionId } = props;\r\n const accordionCtx = useContext(AccordionContext);\r\n const { context: sectionContext, isEmpty } = useAccordionSectionBlockContext(props);\r\n\r\n if (accordionCtx) {\r\n return (\r\n <AccordionSectionBlockContext.Provider value={sectionContext}>\r\n {!isEmpty && <AccordionItem value={sectionId}>{children}</AccordionItem>}\r\n </AccordionSectionBlockContext.Provider>\r\n );\r\n }\r\n\r\n return <AccordionItem value={sectionId}>{children}</AccordionItem>;\r\n};\r\n\r\n/**\r\n * Props: `AccordionSectionItem`.\r\n */\r\nexport type AccordionSectionItemProps = {\r\n /** The ID of the `AccordionSectionItem`, unique within the `AccordionSectionBlock` instance. */\r\n uniqueId: string;\r\n /** The searchable text label for the item. */\r\n label?: string;\r\n /** Whether the item is not interactable. */\r\n staticItem?: boolean;\r\n};\r\n\r\n/**\r\n * Wrapper component that must encapsulate individual items.\r\n * - Renders the pin button and tracks the pinned state of the item.\r\n * - Renders the hide button and tracks the hidden state of the item.\r\n * - Filters items based on the current search term.\r\n *\r\n * @param props - `AccordionSectionItemProps`\r\n * @returns `Portal` if pinned; `null` if hidden/filtered; `children` otherwise.\r\n */\r\nexport const AccordionSectionItem: FunctionComponent<PropsWithChildren<AccordionSectionItemProps>> = (props) => {\r\n AccordionSectionItem.displayName = \"AccordionSectionItem\";\r\n const { children, staticItem } = props;\r\n const classes = useStyles();\r\n const accordionCtx = useContext(AccordionContext);\r\n const itemState = useAccordionSectionItemState(props);\r\n const [ctrlMode, setCtrlMode] = useState(false);\r\n const ctrlPressed = useKeyState(\"Control\");\r\n const [mouseOver, setMouseOver] = useState(false);\r\n\r\n useEffect(() => {\r\n setCtrlMode(ctrlPressed && mouseOver);\r\n }, [ctrlPressed, mouseOver]);\r\n\r\n // If static item or no context, just render children\r\n if (staticItem || !accordionCtx || !itemState) {\r\n return <>{children}</>;\r\n }\r\n\r\n const { pinnedContainerRef, features } = accordionCtx;\r\n const { isNested, isPinned, isHidden, isMatch, pinnedIndex, canMoveUp, inEditMode, actions } = itemState;\r\n\r\n // Nested items just render children (don't show controls)\r\n if (isNested) {\r\n return <>{children}</>;\r\n }\r\n\r\n // If hidden (and not in edit mode) or doesn't match search, don't render\r\n if ((isHidden && !inEditMode) || !isMatch) {\r\n return null;\r\n }\r\n\r\n const pinnedContainer = isPinned ? pinnedContainerRef.current : null;\r\n const showControls = inEditMode || ctrlMode;\r\n\r\n const itemElement = (\r\n <div\r\n className={classes.sectionItemContainer}\r\n style={isPinned ? { order: pinnedIndex } : undefined}\r\n onMouseMove={() => setMouseOver(true)}\r\n onMouseLeave={() => setMouseOver(false)}\r\n >\r\n {showControls && (\r\n <div className={classes.sectionItemButtons}>\r\n {features.hiding && (\r\n <Button title={isHidden ? \"Unhide\" : \"Hide\"} icon={isHidden ? EyeOffRegular : EyeFilled} appearance=\"transparent\" onClick={actions.toggleHidden} />\r\n )}\r\n {features.pinning && (\r\n <>\r\n <Button title={isPinned ? \"Unpin\" : \"Pin\"} icon={isPinned ? PinFilled : PinRegular} appearance=\"transparent\" onClick={actions.togglePinned} />\r\n {isPinned && <Button icon={ArrowCircleUpRegular} appearance=\"transparent\" disabled={!canMoveUp} onClick={actions.movePinnedUp} />}\r\n </>\r\n )}\r\n </div>\r\n )}\r\n <AccordionItemDepthContext.Provider value={true}>\r\n <div className={classes.sectionItemContent}>{children}</div>\r\n </AccordionItemDepthContext.Provider>\r\n </div>\r\n );\r\n\r\n return pinnedContainer ? <Portal mountNode={pinnedContainer}>{itemElement}</Portal> : itemElement;\r\n};\r\n\r\n/**\r\n * Renders the Pinned section container and defines the portal target for the pinned items.\r\n *\r\n * @returns `div`\r\n */\r\nconst AccordionPinnedContainer: FunctionComponent = () => {\r\n AccordionPinnedContainer.displayName = \"AccordionPinnedContainer\";\r\n const classes = useStyles();\r\n const accordionCtx = useContext(AccordionContext);\r\n\r\n return (\r\n <div ref={accordionCtx?.pinnedContainerRef} className={classes.pinnedContainer}>\r\n <MessageBar className={classes.pinnedContainerEmpty}>\r\n <MessageBarBody>No pinned items</MessageBarBody>\r\n </MessageBar>\r\n </div>\r\n );\r\n};\r\n\r\n/**\r\n * Renders the search box for filtering items.\r\n *\r\n * @returns `SearchBox`, or `null` if the feature is disabled.\r\n */\r\nconst AccordionSearchBox: FunctionComponent = () => {\r\n AccordionSearchBox.displayName = \"AccordionSearchBox\";\r\n const classes = useStyles();\r\n const accordionCtx = useContext(AccordionContext);\r\n\r\n if (!accordionCtx?.features.search) {\r\n return null;\r\n }\r\n\r\n const { state, dispatch } = accordionCtx;\r\n\r\n return (\r\n <SearchBox\r\n className={classes.searchBox}\r\n appearance=\"underline\"\r\n contentBefore={<FilterRegular />}\r\n placeholder=\"Filter\"\r\n value={state.searchTerm}\r\n onChange={(_, data) => dispatch({ type: \"SET_SEARCH_TERM\", term: data.value })}\r\n />\r\n );\r\n};\r\n\r\n/**\r\n * Props: `AccordionSection`.\r\n */\r\nexport type AccordionSectionProps = {\r\n /** The text label shown in the section header. */\r\n title: string;\r\n /** Indicates whether the `AccordionSection` is initially collapsed. */\r\n collapseByDefault?: boolean;\r\n};\r\n\r\n/**\r\n * Wrapper component that must encapsulate the section body.\r\n *\r\n * @param props - `AccordionSectionProps`\r\n * @returns `div`\r\n */\r\nexport const AccordionSection: FunctionComponent<PropsWithChildren<AccordionSectionProps>> = (props) => {\r\n AccordionSection.displayName = \"AccordionSection\";\r\n const classes = useStyles();\r\n\r\n return <div className={classes.panelDiv}>{props.children}</div>;\r\n};\r\n\r\n/**\r\n * Props: `Accordion`.\r\n */\r\nexport type AccordionProps = {\r\n /** The unique ID of the `Accordion` instance. */\r\n uniqueId?: string;\r\n /** The list of sections to be highlighted. */\r\n highlightSections?: readonly string[];\r\n /** Enables the pinned items feature. */\r\n enablePinnedItems?: boolean;\r\n /** Enables the hidden items feature. */\r\n enableHiddenItems?: boolean;\r\n /** Enables the search items feature. */\r\n enableSearchItems?: boolean;\r\n};\r\n\r\nconst StringAccordion = FluentAccordion as ForwardRefExoticComponent<FluentAccordionProps<string> & RefAttributes<HTMLDivElement>>;\r\n\r\nexport const Accordion = forwardRef<HTMLDivElement, PropsWithChildren<AccordionProps>>((props, ref) => {\r\n Accordion.displayName = \"Accordion\";\r\n const { children, highlightSections, ...rest } = props;\r\n const classes = useStyles();\r\n const { size } = useContext(ToolContext);\r\n const accordionCtx = useAccordionContext(props);\r\n const hasPinning = accordionCtx?.features.pinning ?? false;\r\n\r\n const pinnedSectionElement = useMemo(() => {\r\n return (\r\n hasPinning && (\r\n <AccordionSection title=\"Pinned\" collapseByDefault={false}>\r\n <AccordionPinnedContainer />\r\n </AccordionSection>\r\n )\r\n );\r\n }, [hasPinning]);\r\n\r\n // Prevents sections contents from unmounting when closed, allowing their elements to be used in the Pinned section.\r\n const preventUnmountMotion: AccordionPanelProps[\"collapseMotion\"] = useMemo(() => {\r\n // https://github.com/microsoft/fluentui/issues/34309#issuecomment-2824364945\r\n // eslint-disable-next-line @typescript-eslint/naming-convention\r\n return hasPinning ? { children: (Component, props) => <Component {...props} unmountOnExit={false} /> } : undefined;\r\n }, [hasPinning]);\r\n\r\n const validChildren = useMemo(() => {\r\n return (\r\n Children.map([pinnedSectionElement, children], (child) => {\r\n if (isValidElement(child)) {\r\n const childProps = child.props as Partial<AccordionSectionProps>;\r\n if (childProps.title) {\r\n return {\r\n title: childProps.title,\r\n collapseByDefault: childProps.collapseByDefault,\r\n content: child,\r\n };\r\n }\r\n }\r\n return null;\r\n })?.filter(Boolean) ?? []\r\n );\r\n }, [children]);\r\n\r\n // Tracks open items, and used to tell the Accordion which sections should be expanded.\r\n const [openItems, setOpenItems] = useState(validChildren.filter((child) => !child.collapseByDefault).map((child) => child.title));\r\n\r\n // Tracks closed items, which is needed so that when the children change, we only update the open/closed state\r\n // (depending on the collapseByDefault prop) for items that have not been explicitly opened or closed.\r\n const [closedItems, setClosedItems] = useState(validChildren.filter((child) => child.collapseByDefault).map((child) => child.title));\r\n\r\n const internalOpenItemsRef = useRef<string[] | undefined>(openItems);\r\n\r\n // When highlight sections is requested, we temporarily override the open items, but if highlight sections is cleared,\r\n // then we revert back to the normal open items tracking.\r\n useLayoutEffect(() => {\r\n if (highlightSections) {\r\n internalOpenItemsRef.current = [...openItems];\r\n setOpenItems([...highlightSections]);\r\n } else {\r\n setOpenItems([...(internalOpenItemsRef.current ?? [])]);\r\n internalOpenItemsRef.current = undefined;\r\n }\r\n }, [highlightSections]);\r\n\r\n useEffect(() => {\r\n for (const defaultOpenItem of validChildren.filter((child) => !child.collapseByDefault).map((child) => child.title)) {\r\n // If a child is not marked as collapseByDefault, then it should be opened by default, and\r\n // it is only \"default\" if it hasn't already been explicitly added to the opened or closed list.\r\n if (!closedItems.includes(defaultOpenItem) && !openItems.includes(defaultOpenItem)) {\r\n setOpenItems((prev) => [...prev, defaultOpenItem]);\r\n }\r\n }\r\n }, [validChildren]);\r\n\r\n const onToggle = useCallback((event: AccordionToggleEvent, data: AccordionToggleData<string>) => {\r\n if (data.openItems.includes(data.value)) {\r\n setOpenItems((prev) => [...prev, data.value]);\r\n setClosedItems((prev) => prev.filter((item) => item !== data.value));\r\n } else {\r\n setClosedItems((prev) => [...prev, data.value]);\r\n setOpenItems((prev) => prev.filter((item) => item !== data.value));\r\n }\r\n }, []);\r\n\r\n return (\r\n <StringAccordion ref={ref} className={classes.accordion} collapsible multiple onToggle={onToggle} openItems={openItems} {...rest}>\r\n <AccordionContext.Provider value={accordionCtx}>\r\n <AccordionMenuBar />\r\n <div className={classes.accordionBody}>\r\n {validChildren.map((child, index) => {\r\n const isHighlighted = highlightSections?.includes(child.title);\r\n return (\r\n <AccordionSectionBlock key={child.content.key ?? child.title} sectionId={child.title}>\r\n <div className={isHighlighted ? classes.highlightDiv : undefined}>\r\n <AccordionHeader size={size}>\r\n <Subtitle2Stronger>{child.title}</Subtitle2Stronger>\r\n </AccordionHeader>\r\n <AccordionPanel collapseMotion={preventUnmountMotion}>\r\n <div className={classes.panelDiv}>{child.content}</div>\r\n </AccordionPanel>\r\n </div>\r\n {index < validChildren.length - 1 && <Divider inset={true} className={size === \"small\" ? classes.dividerSmall : classes.divider} />}\r\n </AccordionSectionBlock>\r\n );\r\n })}\r\n </div>\r\n </AccordionContext.Provider>\r\n </StringAccordion>\r\n );\r\n});\r\n"]}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@onerjs/shared-ui-components",
3
- "version": "8.41.5",
3
+ "version": "8.41.6",
4
4
  "main": "index.js",
5
5
  "module": "index.js",
6
6
  "types": "index.d.ts",