@academix-admin/selection-viewer 0.2.0 → 0.2.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.cjs CHANGED
@@ -206,6 +206,34 @@ var useInjectStyles = (id) => {
206
206
  };
207
207
  }, [id]);
208
208
  };
209
+ var useModalKeys = (isOpen, onClose, containerId) => {
210
+ React.useEffect(() => {
211
+ if (!isOpen || typeof document === "undefined") return;
212
+ const onKeyDown = (e) => {
213
+ if (e.key === "Escape") {
214
+ e.preventDefault();
215
+ onClose();
216
+ return;
217
+ }
218
+ if (e.key !== "Tab") return;
219
+ const focusable = document.getElementById(containerId)?.querySelectorAll(
220
+ 'a[href], button:not([disabled]), input:not([disabled]), select:not([disabled]), textarea:not([disabled]), [tabindex]:not([tabindex="-1"])'
221
+ );
222
+ if (!focusable || focusable.length === 0) return;
223
+ const first = focusable[0];
224
+ const last = focusable[focusable.length - 1];
225
+ if (e.shiftKey && document.activeElement === first) {
226
+ e.preventDefault();
227
+ last.focus();
228
+ } else if (!e.shiftKey && document.activeElement === last) {
229
+ e.preventDefault();
230
+ first.focus();
231
+ }
232
+ };
233
+ document.addEventListener("keydown", onKeyDown);
234
+ return () => document.removeEventListener("keydown", onKeyDown);
235
+ }, [isOpen, onClose, containerId]);
236
+ };
209
237
  var SelectionViewer = ({
210
238
  id: providedId,
211
239
  isOpen,
@@ -225,6 +253,7 @@ var SelectionViewer = ({
225
253
  initialSnap = 1,
226
254
  unmountOnClose = true,
227
255
  zIndex = 1e3,
256
+ ariaLabel,
228
257
  maxHeight = "90dvh",
229
258
  minHeight = "65dvh",
230
259
  selectionState: selectionStateProp = "initial",
@@ -241,6 +270,7 @@ var SelectionViewer = ({
241
270
  const sheetRef = React.useRef(null);
242
271
  React.useRef(null);
243
272
  useInjectStyles(id);
273
+ useModalKeys(isOpen, onClose, id);
244
274
  const [reportedStates, setReportedStates] = React.useState(/* @__PURE__ */ new Map());
245
275
  const reportAggregate = React.useCallback((reporterId, state) => {
246
276
  setReportedStates((prev) => {
@@ -358,6 +388,9 @@ var SelectionViewer = ({
358
388
  modalSheet.Sheet.Container,
359
389
  {
360
390
  id,
391
+ role: "dialog",
392
+ "aria-modal": "true",
393
+ "aria-label": ariaLabel,
361
394
  style: {
362
395
  maxHeight,
363
396
  minHeight: isSearchFocused ? "100dvh" : minHeight,
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/SelectionViewer.tsx","../src/Row.tsx","../src/Column.tsx"],"names":["React","useEffect","useState","useRef","useCallback","useMemo","jsx","jsxs","Sheet","Fragment"],"mappings":"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","file":"index.cjs","sourcesContent":["import React, { useState, useEffect, useCallback, useRef, useMemo } from \"react\";\nimport { Sheet } from \"@academix-admin/modal-sheet\";\n\n// ==================== Aggregation (Row/Column) ====================\n// Independent from @academix-admin/search-viewer's equivalent (Library Charter: packages stay\n// mutually independent) — same shape, duplicated intentionally rather than shared.\n\ntype AggregateReporter = {\n report: (id: string, state: SelectionState) => void;\n unreport: (id: string) => void;\n};\n\n/** A `Row` reports its own `state` into the nearest `Column` through this. */\nconst RowAggregateContext = React.createContext<AggregateReporter | null>(null);\n\n/** `Column` reports its own aggregated state up through this — `SelectionViewer` provides it and\n * merges whatever's reported into its own selectionState resolution, with zero extra wiring. */\nconst SelectionViewerAggregateContext = React.createContext<AggregateReporter | null>(null);\n\nfunction computeAggregateState(states: SelectionState[]): SelectionState {\n if (states.length === 0) return \"initial\";\n if (states.some((s) => s === \"data\")) return \"data\";\n if (states.some((s) => s === \"loading\")) return \"loading\";\n if (states.every((s) => s === \"empty\")) return \"empty\";\n if (states.some((s) => s === \"error\")) return \"error\";\n return \"initial\";\n}\n\n// ==================== Types ====================\ntype Padding = {\n l: string;\n r: string;\n t: string;\n b: string;\n};\n\ntype SnapPoint = number;\n\ntype SelectionState = \"loading\" | \"empty\" | \"error\" | \"data\" | \"initial\";\n\n\ntype TitleProps = {\n text: string;\n textColor: string;\n className?: string;\n containerClass?: string;\n style?: React.CSSProperties;\n};\n\ntype SearchProps = {\n text: string;\n textColor: string;\n className?: string;\n background?: string;\n prefixIcon?: React.ReactNode;\n suffixIcon?: React.ReactNode;\n clearIcon?: React.ReactNode;\n backIcon?: React.ReactNode;\n prefixGap?: string;\n suffixGap?: string;\n padding?: Padding;\n autoFocus?: boolean;\n inputStyle?: React.CSSProperties;\n containerStyle?: React.CSSProperties;\n onChange?: (value: string) => void;\n onFocus?: () => void;\n onBlur?: () => void;\n};\n\ntype LoadingProps = {\n view: React.ReactNode;\n padding?: Padding;\n style?: React.CSSProperties;\n};\n\ntype NoResultProps = {\n view: React.ReactNode;\n text?: string;\n padding?: Padding;\n style?: React.CSSProperties;\n};\n\ntype ErrorProps = {\n view: React.ReactNode;\n text?: string;\n padding?: Padding;\n style?: React.CSSProperties;\n};\n\ntype CancelButtonProps = {\n text?: string;\n view: React.ReactNode;\n position?: \"left\" | \"right\";\n style?: React.CSSProperties;\n onClick?: () => void;\n};\n\ntype LayoutProps = {\n gapBetweenHandleAndTitle?: string;\n gapBetweenTitleAndSearch?: string;\n gapBetweenSearchAndContent?: string;\n backgroundColor?: string;\n handleColor?: string;\n handleWidth?: string;\n fullScreenSearchBackground?: string;\n fullScreenSearchHeaderStyle?: React.CSSProperties;\n maxWidth?: string;\n};\n\ntype SelectionViewerProps = {\n id?: string;\n isOpen: boolean;\n backDrop?: boolean;\n onClose: () => void;\n titleProp: TitleProps;\n searchProp?: SearchProps;\n loadingProp?: LoadingProps;\n noResultProp?: NoResultProps;\n errorProp?: ErrorProps;\n cancelButton?: CancelButtonProps;\n layoutProp?: LayoutProps;\n childrenDirection?: \"vertical\" | \"horizontal\";\n children?: React.ReactNode;\n onPaginate?: () => boolean | Promise<boolean>;\n snapPoints?: SnapPoint[];\n initialSnap?: number;\n unmountOnClose?: boolean;\n zIndex?: number;\n maxHeight?: string;\n minHeight?: string;\n selectionState?: SelectionState;\n closeThreshold?: number;\n};\n\n// ==================== Styles ====================\nconst getStyles = (id: string) => `\n#${id} .selection-viewer-header {\n padding: 0px;\n display: flex;\n flex-direction: column;\n align-items: center;\n position: relative;\n width: 100%;\n}\n\n#${id} .selection-viewer-drag-handle {\n height: 5px;\n border-radius: 3px;\n margin-top: 16px;\n}\n\n#${id} .selection-viewer-container {\n display: flex;\n align-items: flex-start;\n width: 100%;\n}\n\n#${id} .selection-viewer-title {\n margin: 0px;\n font-size: 18px;\n font-weight: 600;\n padding: 0px 16px 0px 16px;\n word-break: break-word; /* break long words */\n white-space: normal; /* allow wrapping */\n}\n\n#${id} .selection-viewer-search {\n display: flex;\n align-items: center;\n margin: 16px 16px 4px 16px;\n border-radius: 12px;\n box-sizing: border-box;\n border: 1px solid rgba(0, 0, 0, 0.1);\n}\n\n#${id} .selection-viewer-search-input {\n flex: 1;\n border: none;\n background: transparent;\n padding: 12px 8px;\n outline: none;\n font-size: 16px !important;\n width: 100%;\n}\n\n#${id} .selection-viewer-content {\n overflow-y: auto;\n -webkit-overflow-scrolling: touch;\n flex: 1;\n min-height: 0;\n}\n\n#${id} .selection-viewer-content.vertical {\n display: flex;\n flex-direction: column;\n gap: 8px;\n}\n\n#${id} .selection-viewer-content.horizontal {\n display: flex;\n flex-direction: row;\n gap: 8px;\n overflow-x: auto;\n overflow-y: hidden;\n}\n\n#${id} .selection-viewer-no-results,\n#${id} .selection-viewer-error,\n#${id} .selection-viewer-loading {\n display: flex;\n justify-content: center;\n align-items: center;\n min-height: 120px;\n}\n\n#${id} .selection-viewer-default-no-results {\n color: #666;\n font-size: 14px;\n}\n\n#${id} .selection-viewer-default-error {\n color: red;\n font-size: 14px;\n}\n\n/* Full screen search mode */\n#${id} .selection-viewer-fullscreen-search {\n// position: fixed;\n top: 0;\n left: 0;\n right: 0;\n z-index: 10;\n// padding-top: env(safe-area-inset-top);\n width: 100%;\n}\n\n#${id} .selection-viewer-search-back-button {\n background: none;\n border: none;\n padding: 8px;\n margin-right: 4px;\n display: flex;\n align-items: center;\n justify-content: center;\n cursor: pointer;\n transition: opacity 0.2s;\n}\n\n#${id} .selection-viewer-search-back-button:hover {\n opacity: 0.7;\n}\n\n#${id} .selection-viewer-search-clear-button {\n background: none;\n border: none;\n padding: 8px;\n margin-left: 4px;\n display: flex;\n align-items: center;\n justify-content: center;\n cursor: pointer;\n transition: opacity 0.2s;\n}\n\n#${id} .selection-viewer-search-clear-button:hover {\n opacity: 0.7;\n}\n\n/* React Modal Sheet overrides */\n#${id} .react-modal-sheet-container {\n max-width: 500px;\n margin: 0 auto;\n border-top-left-radius: 16px;\n border-top-right-radius: 16px;\n}\n\n#${id} .react-modal-sheet-backdrop {\n background-color: rgba(0, 0, 0, 0.5) !important;\n pointer-events: auto !important;\n}\n\n#${id} .react-modal-sheet-content {\n padding: 0 0px 0px 0px;\n height: 100%;\n}\n\n\n/* Mobile full-width behavior */\n@media (max-width: 500px) {\n #${id} .react-modal-sheet-container {\n max-width: 100%;\n border-radius: 0;\n }\n}\n\n/* Prevent iOS zooming */\n@media screen and (-webkit-min-device-pixel-ratio: 0) {\n #${id} .selection-viewer-search-input {\n font-size: 16px !important;\n }\n}\n`;\n\n// ==================== Hook to inject CSS per instance ====================\nconst useInjectStyles = (id: string) => {\n useEffect(() => {\n const styleId = `selection-viewer-styles-${id}`;\n let styleTag = document.getElementById(styleId) as HTMLStyleElement | null;\n\n if (!styleTag) {\n styleTag = document.createElement(\"style\");\n styleTag.id = styleId;\n styleTag.innerHTML = getStyles(id);\n document.head.appendChild(styleTag);\n }\n\n // Cleanup on unmount\n return () => {\n if (styleTag && document.head.contains(styleTag)) {\n document.head.removeChild(styleTag);\n }\n };\n }, [id]);\n};\n\n// ==================== Component ====================\nconst SelectionViewer: React.FC<SelectionViewerProps> = ({\n id: providedId,\n isOpen,\n backDrop = true,\n onClose,\n titleProp,\n searchProp,\n loadingProp,\n noResultProp,\n errorProp,\n cancelButton,\n layoutProp,\n childrenDirection = \"vertical\",\n children,\n onPaginate,\n snapPoints = [0, 1],\n initialSnap = 1,\n unmountOnClose = true,\n zIndex = 1000,\n maxHeight = \"90dvh\",\n minHeight = \"65dvh\",\n selectionState: selectionStateProp = \"initial\",\n closeThreshold = 0.2,\n}) => {\n const [id] = useState(() => providedId || `selection-${Math.random().toString(36).substring(2, 11)}`);\n const [searchValue, setSearchValue] = useState(\"\");\n const [isSearchFocused, setIsSearchFocused] = useState(false);\n const [keyboardHeight, setKeyboardHeight] = useState(0);\n const [inputKey, setInputKey] = useState(0);\n const [shouldAutoFocus, setShouldAutoFocus] = useState(false);\n const isPaginating = useRef(false);\n const searchInputRef = useRef<HTMLInputElement>(null);\n const sheetRef = useRef<any>(null);\n const headerRef = useRef<HTMLDivElement>(null);\n\n useInjectStyles(id);\n\n // Descendant sections (a Column, or anything else) can report a cumulative state up through this —\n // starts empty, so a plain SelectionViewer with no Row/Column children behaves exactly as before.\n const [reportedStates, setReportedStates] = useState<Map<string, SelectionState>>(new Map());\n const reportAggregate = useCallback((reporterId: string, state: SelectionState) => {\n setReportedStates((prev) => {\n const next = new Map(prev);\n next.set(reporterId, state);\n return next;\n });\n }, []);\n const unreportAggregate = useCallback((reporterId: string) => {\n setReportedStates((prev) => {\n if (!prev.has(reporterId)) return prev;\n const next = new Map(prev);\n next.delete(reporterId);\n return next;\n });\n }, []);\n const aggregateReporterValue = useMemo(\n () => ({ report: reportAggregate, unreport: unreportAggregate }),\n [reportAggregate, unreportAggregate]\n );\n const reportedAggregate =\n reportedStates.size > 0 ? computeAggregateState(Array.from(reportedStates.values())) : null;\n const isComposed = reportedAggregate !== null;\n\n // Precedence: an explicit `selectionState` prop always wins (matches today's exact behaviour for\n // any consumer not using Row/Column) -> then a reported Column aggregate, if one exists -> \"initial\".\n const selectionState =\n selectionStateProp !== \"initial\" ? selectionStateProp : reportedAggregate ?? \"initial\";\n\n // Track keyboard height\n useEffect(() => {\n if (typeof window === 'undefined' || !window.visualViewport) return;\n\n const handleResize = () => {\n const vp = window.visualViewport!;\n const kbHeight = window.innerHeight - vp.height;\n setKeyboardHeight(kbHeight > 0 ? kbHeight : 0);\n };\n\n window.visualViewport.addEventListener('resize', handleResize);\n window.visualViewport.addEventListener('scroll', handleResize);\n\n return () => {\n window.visualViewport?.removeEventListener('resize', handleResize);\n window.visualViewport?.removeEventListener('scroll', handleResize);\n };\n }, []);\n\n // Auto-focus on search\n useEffect(() => {\n if (!isOpen) {\n searchInputRef.current?.blur();\n setSearchValue(\"\");\n searchProp?.onChange?.(\"\");\n setShouldAutoFocus(false);\n return;\n }\n }, [isOpen, searchProp?.autoFocus]);\n\n const handleOpenEnd = useCallback(() => {\n if (searchProp?.autoFocus && searchInputRef.current) {\n setInputKey(prev => prev + 1);\n setShouldAutoFocus(true);\n searchInputRef.current.focus();\n searchInputRef.current.click();\n }\n }, [searchProp?.autoFocus]);\n\n const handleSearchChange = (e: React.ChangeEvent<HTMLInputElement>) => {\n const value = e.target.value;\n setSearchValue(value);\n searchProp?.onChange?.(value);\n };\n\n const handleSearchFocus = () => {\n setIsSearchFocused(true);\n searchProp?.onFocus?.();\n requestAnimationFrame(() => {\n searchInputRef.current?.focus();\n });\n };\n\n const handleSearchBlur = () => {\n searchProp?.onBlur?.();\n };\n\n const handleBackFromSearch = () => {\n setIsSearchFocused(false);\n if (searchInputRef.current) {\n searchInputRef.current.blur();\n }\n };\n\n const clearSearch = () => {\n setSearchValue(\"\");\n searchProp?.onChange?.(\"\");\n if (searchInputRef.current) {\n searchInputRef.current.focus();\n }\n };\n\n const handleScroll = useCallback(\n async (e: React.UIEvent<HTMLDivElement>) => {\n if (isPaginating.current || !onPaginate) return;\n\n const { scrollTop, scrollHeight, clientHeight } = e.currentTarget;\n const isNearBottom = scrollHeight - scrollTop <= clientHeight * 1.2;\n\n if (isNearBottom) {\n isPaginating.current = true;\n const hasMore = await onPaginate();\n if (!hasMore) {\n isPaginating.current = false;\n } else {\n setTimeout(() => {\n isPaginating.current = false;\n }, 500);\n }\n }\n },\n [onPaginate]\n );\n\n if (!isOpen && unmountOnClose) return null;\n\n return (\n <SelectionViewerAggregateContext.Provider value={aggregateReporterValue}>\n <Sheet\n ref={sheetRef}\n isOpen={isOpen}\n onClose={onClose}\n detent=\"content\"\n style={{ zIndex }}\n maxHeight={maxHeight}\n onOpenEnd={handleOpenEnd}\n >\n <Sheet.Container\n id={id}\n style={{\n maxHeight: maxHeight,\n minHeight: isSearchFocused ? \"100dvh\" : minHeight,\n maxWidth: layoutProp?.maxWidth ?? '800px',\n margin: \"0 auto\",\n width: \"100%\",\n left: 0,\n right: 0,\n paddingBottom: \"calc(0px + env(safe-area-inset-bottom))\",\n background: isSearchFocused\n ? layoutProp?.fullScreenSearchBackground || layoutProp?.backgroundColor\n : layoutProp?.backgroundColor,\n borderTopLeftRadius: isSearchFocused ? \"0px\" : \"16px\",\n borderTopRightRadius: isSearchFocused ? \"0px\" : \"16px\",\n }}\n >\n {isSearchFocused ? (\n <Sheet.Header>\n <div\n className=\"selection-viewer-fullscreen-search\"\n style={layoutProp?.fullScreenSearchHeaderStyle}\n >\n <div className=\"selection-viewer-search\" style={{\n ...searchProp?.containerStyle,\n background: searchProp?.background,\n padding: searchProp?.padding\n ? `${searchProp.padding.t} ${searchProp.padding.r} ${searchProp.padding.b} ${searchProp.padding.l}`\n : \"16px\"\n }}>\n <button\n className=\"selection-viewer-search-back-button\"\n onClick={handleBackFromSearch}\n aria-label=\"Exit search mode\"\n >\n {searchProp?.backIcon || (\n <svg width=\"24\" height=\"24\" viewBox=\"0 0 24 24\" fill=\"none\" xmlns=\"http://www.w3.org/2000/svg\">\n <path d=\"M15 18L9 12L15 6\" stroke={searchProp?.textColor || 'currentColor'} strokeWidth=\"2\" strokeLinecap=\"round\" strokeLinejoin=\"round\" />\n </svg>\n )}\n </button>\n\n <input\n key={inputKey}\n ref={searchInputRef}\n type=\"text\"\n placeholder={searchProp?.text}\n value={searchValue}\n onChange={handleSearchChange}\n className={searchProp?.className || \"selection-viewer-search-input\"}\n style={{\n color: searchProp?.textColor,\n ...searchProp?.inputStyle\n }}\n onFocus={handleSearchFocus}\n onBlur={handleSearchBlur}\n autoFocus={shouldAutoFocus}\n />\n\n {searchValue && (\n <button\n className=\"selection-viewer-search-clear-button\"\n onClick={clearSearch}\n aria-label=\"Clear search\"\n >\n {searchProp?.clearIcon || (\n <svg width=\"24\" height=\"24\" viewBox=\"0 0 24 24\" fill=\"none\" xmlns=\"http://www.w3.org/2000/svg\">\n <path d=\"M18 6L6 18M6 6L18 18\" stroke={searchProp?.textColor || 'currentColor'} strokeWidth=\"2\" strokeLinecap=\"round\" strokeLinejoin=\"round\" />\n </svg>\n )}\n </button>\n )}\n </div>\n </div>\n </Sheet.Header>\n ) : (\n <Sheet.Header>\n <div className=\"selection-viewer-header\">\n {/* Cancel button left */}\n {cancelButton?.position === \"left\" && (\n <button\n style={{\n position: \"absolute\",\n left: \"0px\",\n top: \"8px\",\n border: \"none\",\n backgroundColor: \"transparent\",\n ...cancelButton.style\n }}\n onClick={cancelButton.onClick || onClose}\n >\n {cancelButton.view || cancelButton.text || \"Cancel\"}\n </button>\n )}\n\n {/* Drag handle */}\n {!isSearchFocused && (\n <div\n className=\"selection-viewer-drag-handle\"\n style={{\n background: layoutProp?.handleColor || \"#ccc\",\n width: layoutProp?.handleWidth || \"40px\",\n marginBottom: layoutProp?.gapBetweenHandleAndTitle || \"12px\",\n }}\n />\n )}\n\n {/* Cancel button right */}\n {cancelButton?.position === \"right\" && (\n <button\n style={{\n position: \"absolute\",\n right: \"0px\",\n top: \"8px\",\n border: \"none\",\n backgroundColor: \"transparent\",\n ...cancelButton.style\n }}\n onClick={cancelButton.onClick || onClose}\n >\n {cancelButton.view || cancelButton.text || \"Cancel\"}\n </button>\n )}\n\n {/* Title */}\n <div className={titleProp.containerClass || \"selection-viewer-container\"}>\n <h2\n id={`${id}-title`}\n className={titleProp.className || \"selection-viewer-title\"}\n style={{\n marginBottom: layoutProp?.gapBetweenTitleAndSearch || \"8px\",\n color: titleProp?.textColor || 'black',\n ...titleProp.style\n }}\n >\n {titleProp.text}\n </h2>\n </div>\n </div>\n\n {/* Search */}\n {searchProp && (\n <div\n className=\"selection-viewer-search\"\n style={{\n background: searchProp.background,\n padding: searchProp.padding\n ? `${searchProp.padding.t} ${searchProp.padding.r} ${searchProp.padding.b} ${searchProp.padding.l}`\n : \"8px 16px\",\n marginBottom: layoutProp?.gapBetweenSearchAndContent,\n ...searchProp.containerStyle\n }}\n >\n {searchProp.prefixIcon && (\n <span style={{ marginRight: searchProp.prefixGap || \"8px\" }}>\n {searchProp.prefixIcon}\n </span>\n )}\n <input\n key={inputKey}\n ref={searchInputRef}\n type=\"text\"\n placeholder={searchProp.text}\n value={searchValue}\n onChange={handleSearchChange}\n className={searchProp.className || \"selection-viewer-search-input\"}\n style={{\n color: searchProp?.textColor,\n ...searchProp.inputStyle\n }}\n onFocus={handleSearchFocus}\n onBlur={handleSearchBlur}\n autoFocus={shouldAutoFocus}\n />\n {searchValue && (\n <button\n className=\"selection-viewer-search-clear-button\"\n onClick={clearSearch}\n aria-label=\"Clear search\"\n style={{ marginLeft: searchProp.suffixGap || \"8px\" }}\n >\n {searchProp.clearIcon || searchProp.suffixIcon || (\n <svg width=\"24\" height=\"24\" viewBox=\"0 0 24 24\" fill=\"none\" xmlns=\"http://www.w3.org/2000/svg\">\n <path d=\"M18 6L6 18M6 6L18 18\" stroke=\"currentColor\" strokeWidth=\"2\" strokeLinecap=\"round\" strokeLinejoin=\"round\" />\n </svg>\n )}\n </button>\n )}\n {!searchValue && searchProp.suffixIcon && (\n <span style={{ marginLeft: searchProp.suffixGap || \"8px\" }}>\n {searchProp.suffixIcon}\n </span>\n )}\n </div>\n )}\n </Sheet.Header>\n )}\n\n <Sheet.Content>\n <div\n className={`selection-viewer-content ${childrenDirection}`}\n onScroll={onPaginate ? handleScroll : undefined}\n style={{\n paddingTop: isSearchFocused ? layoutProp?.gapBetweenSearchAndContent : '0',\n paddingBottom: keyboardHeight > 0\n ? `${keyboardHeight + 16}px`\n : '16px',\n }}\n >\n {/* Show children first, then loading at bottom */}\n {React.Children.count(children) > 0 ? (\n <>\n {children}\n {selectionState === \"loading\" && (\n <div\n className=\"selection-viewer-loading\"\n style={{\n padding: loadingProp?.padding\n ? `${loadingProp.padding.t} ${loadingProp.padding.r} ${loadingProp.padding.b} ${loadingProp.padding.l}`\n : \"16px\",\n ...loadingProp?.style\n }}\n >\n {loadingProp?.view}\n </div>\n )}\n {/* Composed mode: a Column/Row descendant reports its own state, which can only ever be\n \"empty\"/\"error\" here since the child count > 0 branch is unconditional on a literal\n <Column> being present. Layer the outer view alongside the (visually empty) children\n rather than replacing them — a Column/Row must stay mounted to keep reporting. */}\n {isComposed && selectionState === \"empty\" && (\n <div\n className=\"selection-viewer-no-results\"\n style={{\n padding: noResultProp?.padding\n ? `${noResultProp.padding.t} ${noResultProp.padding.r} ${noResultProp.padding.b} ${noResultProp.padding.l}`\n : \"16px\",\n ...noResultProp?.style\n }}\n >\n {noResultProp?.view || (\n <div className=\"selection-viewer-default-no-results\">\n {noResultProp?.text || \"No results found\"}\n </div>\n )}\n </div>\n )}\n {isComposed && selectionState === \"error\" && (\n <div\n className=\"selection-viewer-error\"\n style={{\n padding: errorProp?.padding\n ? `${errorProp.padding.t} ${errorProp.padding.r} ${errorProp.padding.b} ${errorProp.padding.l}`\n : \"16px\",\n ...errorProp?.style\n }}\n >\n {errorProp?.view || (\n <div className=\"selection-viewer-default-error\">\n {errorProp?.text || \"No results found\"}\n </div>\n )}\n </div>\n )}\n </>\n ) : (selectionState === \"empty\" || (React.Children.count(children) <= 0 && (selectionState != \"loading\" && selectionState != \"error\"))) ? (\n <div\n className=\"selection-viewer-no-results\"\n style={{\n padding: noResultProp?.padding\n ? `${noResultProp.padding.t} ${noResultProp.padding.r} ${noResultProp.padding.b} ${noResultProp.padding.l}`\n : \"16px\",\n ...noResultProp?.style\n }}\n >\n {noResultProp?.view || (\n <div className=\"selection-viewer-default-no-results\">\n {noResultProp?.text || \"No results found\"}\n </div>\n )}\n </div>\n ) : selectionState === \"loading\" ? (\n <div\n className=\"selection-viewer-loading\"\n style={{\n padding: loadingProp?.padding\n ? `${loadingProp.padding.t} ${loadingProp.padding.r} ${loadingProp.padding.b} ${loadingProp.padding.l}`\n : \"16px\",\n ...loadingProp?.style\n }}\n >\n {loadingProp?.view}\n </div>\n ) : (selectionState === \"error\") ? (\n <div\n className=\"selection-viewer-error\"\n style={{\n padding: errorProp?.padding\n ? `${errorProp.padding.t} ${errorProp.padding.r} ${errorProp.padding.b} ${errorProp.padding.l}`\n : \"16px\",\n ...errorProp?.style\n }}\n >\n {errorProp?.view || (\n <div className=\"selection-viewer-default-error\">\n {errorProp?.text || \"No results found\"}\n </div>\n )}\n </div>\n ) : null}\n </div>\n </Sheet.Content>\n </Sheet.Container>\n <Sheet.Backdrop onTap={backDrop ? onClose : undefined} />\n </Sheet>\n </SelectionViewerAggregateContext.Provider>\n );\n};\n\n// ==================== Controller Hook ====================\ntype Operation = {\n open: () => void;\n close: () => void;\n toggle: () => void;\n setSelectionState: (val: SelectionState) => void;\n};\n\nconst useSelectionController = (initialSelectionState?: SelectionState): [\n string,\n Operation,\n boolean,\n SelectionState\n] => {\n const [isOpen, setIsOpen] = useState(false);\n const [selectionState, setSelectionState] = useState(initialSelectionState || 'initial');\n const [selectionId] = useState(() => `selection-${Math.random().toString(36).substring(2, 11)}`);\n\n const operations = useMemo<Operation>(() => ({\n open: () => setIsOpen(true),\n close: () => setIsOpen(false),\n toggle: () => setIsOpen((prev) => !prev),\n setSelectionState\n }), [setSelectionState]);\n\n return [selectionId, operations, isOpen, selectionState];\n};\n\nexport { SelectionViewer, useSelectionController, RowAggregateContext, SelectionViewerAggregateContext, computeAggregateState };\nexport type {\n SelectionViewerProps,\n SelectionState,\n TitleProps,\n SearchProps,\n LoadingProps,\n NoResultProps,\n ErrorProps,\n CancelButtonProps,\n LayoutProps,\n Padding,\n SnapPoint,\n AggregateReporter,\n};\nexport default SelectionViewer;\n","import React, { useCallback, useEffect, useRef, useState } from \"react\";\nimport { RowAggregateContext } from \"./SelectionViewer\";\nimport type { SelectionState } from \"./SelectionViewer\";\n\nexport type RowProps = {\n id?: string;\n /** Consumer-owned — SelectionViewer has never owned fetch/filter state, so unlike\n * search-viewer's Row this isn't internally computed. Mirrors how `selectionState`\n * is already a prop on SelectionViewer itself today. Defaults to \"data\": if you\n * render children without wiring this, we assume what you rendered IS the data. */\n state?: SelectionState;\n /** Called when this Row is scrolled horizontally near its end. Return (or resolve to)\n * `true` if more data may follow (keeps the pagination trigger armed), `false` once\n * there's nothing left to fetch — mirrors SelectionViewer's own `onPaginate` contract. */\n onPaginate?: () => boolean | Promise<boolean>;\n className?: string;\n style?: React.CSSProperties;\n children?: React.ReactNode;\n};\n\n/** A horizontally-scrolling, independently-paginating section — the Row/Column\n * equivalent for `SelectionViewer`. No shared code with `@academix-admin/search-viewer`'s\n * Row (Library Charter: packages stay mutually independent) — this one has no\n * query/debounce/cache engine of its own since `SelectionViewer` never had one either;\n * the consumer owns fetching/filtering and just tells this Row what `state` it's in. */\nfunction Row({ id: providedId, state = \"data\", onPaginate, className, style, children }: RowProps) {\n const aggregateReporter = React.useContext(RowAggregateContext);\n const [rowId] = useState(() => providedId || `row-${Math.random().toString(36).substring(2, 11)}`);\n const containerRef = useRef<HTMLDivElement | null>(null);\n const isPaginating = useRef(false);\n\n const handleScroll = useCallback(async () => {\n const el = containerRef.current;\n if (!el || isPaginating.current || !onPaginate) return;\n\n // Same \"near the end\" threshold as SelectionViewer's own vertical pagination trigger, adapted\n // to horizontal scroll metrics since a Row scrolls sideways.\n const { scrollLeft, scrollWidth, clientWidth } = el;\n if (scrollWidth - scrollLeft > clientWidth * 1.2) return;\n\n isPaginating.current = true;\n const hasMore = await onPaginate();\n if (!hasMore) {\n isPaginating.current = false;\n } else {\n setTimeout(() => {\n isPaginating.current = false;\n }, 500);\n }\n }, [onPaginate]);\n\n useEffect(() => {\n const el = containerRef.current;\n if (!el || !onPaginate) return;\n el.addEventListener(\"scroll\", handleScroll);\n return () => el.removeEventListener(\"scroll\", handleScroll);\n }, [handleScroll, onPaginate]);\n\n useEffect(() => {\n aggregateReporter?.report(rowId, state);\n return () => aggregateReporter?.unreport(rowId);\n }, [aggregateReporter, rowId, state]);\n\n return (\n <div\n ref={containerRef}\n className={className ? `selection-viewer-row ${className}` : \"selection-viewer-row\"}\n style={{\n display: \"flex\",\n flexDirection: \"row\",\n gap: \"8px\",\n overflowX: \"auto\",\n overflowY: \"hidden\",\n ...style,\n }}\n >\n {children}\n </div>\n );\n}\n\nRow.displayName = \"Row\";\n\nexport { Row };\n","import React, { useCallback, useEffect, useMemo, useState } from \"react\";\nimport { RowAggregateContext, SelectionViewerAggregateContext, computeAggregateState } from \"./SelectionViewer\";\nimport type { SelectionState } from \"./SelectionViewer\";\n\nexport type ColumnProps = {\n id?: string;\n className?: string;\n style?: React.CSSProperties;\n children?: React.ReactNode;\n};\n\n/** A vertical arrangement of `Row`s (or other content) — the explicit, composable\n * equivalent of today's flat `children` list. Its default layout is deliberately\n * identical to the existing `.selection-viewer-content.vertical` rendering\n * (`flex-direction: column, gap: 8px`), so today's flat usage is, unchanged, \"an\n * implicit Column with no Rows.\"\n *\n * Provides the `RowAggregateContext` its `Row` children report into, computes ONE\n * cumulative state from everything reported, and is itself a reporter one level up:\n * nested inside another `Column` it reports through that Column's `RowAggregateContext`\n * (behaving like a Row); at the top level it reports through `SelectionViewerAggregateContext`,\n * which `SelectionViewer` provides — this drives the outer sheet's loading/empty/error\n * views automatically with zero manual wiring, and lets Columns nest arbitrarily deep. */\nfunction Column({ id: providedId, className, style, children }: ColumnProps) {\n const [columnId] = useState(\n () => providedId || `column-${Math.random().toString(36).substring(2, 11)}`\n );\n\n const [reportedStates, setReportedStates] = useState<Map<string, SelectionState>>(new Map());\n const report = useCallback((id: string, state: SelectionState) => {\n setReportedStates((prev) => {\n const next = new Map(prev);\n next.set(id, state);\n return next;\n });\n }, []);\n const unreport = useCallback((id: string) => {\n setReportedStates((prev) => {\n if (!prev.has(id)) return prev;\n const next = new Map(prev);\n next.delete(id);\n return next;\n });\n }, []);\n const rowAggregateValue = useMemo(() => ({ report, unreport }), [report, unreport]);\n\n const aggregateState =\n reportedStates.size > 0 ? computeAggregateState(Array.from(reportedStates.values())) : \"initial\";\n\n const parentRowAggregate = React.useContext(RowAggregateContext);\n const selectionViewerAggregate = React.useContext(SelectionViewerAggregateContext);\n const upstreamReporter = parentRowAggregate ?? selectionViewerAggregate;\n\n useEffect(() => {\n if (!upstreamReporter) return;\n upstreamReporter.report(columnId, aggregateState);\n return () => upstreamReporter.unreport(columnId);\n }, [upstreamReporter, columnId, aggregateState]);\n\n return (\n <RowAggregateContext.Provider value={rowAggregateValue}>\n <div\n className={className ? `selection-viewer-column ${className}` : \"selection-viewer-column\"}\n style={{ display: \"flex\", flexDirection: \"column\", gap: \"8px\", ...style }}\n >\n {children}\n </div>\n </RowAggregateContext.Provider>\n );\n}\n\nColumn.displayName = \"Column\";\n\nexport { Column };\n"]}
1
+ {"version":3,"sources":["../src/SelectionViewer.tsx","../src/Row.tsx","../src/Column.tsx"],"names":["React","useEffect","useState","useRef","useCallback","useMemo","jsx","jsxs","Sheet","Fragment"],"mappings":"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","file":"index.cjs","sourcesContent":["import React, { useState, useEffect, useCallback, useRef, useMemo } from \"react\";\r\nimport { Sheet } from \"@academix-admin/modal-sheet\";\r\n\r\n// ==================== Aggregation (Row/Column) ====================\r\n// Independent from @academix-admin/search-viewer's equivalent (Library Charter: packages stay\r\n// mutually independent) — same shape, duplicated intentionally rather than shared.\r\n\r\ntype AggregateReporter = {\r\n report: (id: string, state: SelectionState) => void;\r\n unreport: (id: string) => void;\r\n};\r\n\r\n/** A `Row` reports its own `state` into the nearest `Column` through this. */\r\nconst RowAggregateContext = React.createContext<AggregateReporter | null>(null);\r\n\r\n/** `Column` reports its own aggregated state up through this — `SelectionViewer` provides it and\r\n * merges whatever's reported into its own selectionState resolution, with zero extra wiring. */\r\nconst SelectionViewerAggregateContext = React.createContext<AggregateReporter | null>(null);\r\n\r\nfunction computeAggregateState(states: SelectionState[]): SelectionState {\r\n if (states.length === 0) return \"initial\";\r\n if (states.some((s) => s === \"data\")) return \"data\";\r\n if (states.some((s) => s === \"loading\")) return \"loading\";\r\n if (states.every((s) => s === \"empty\")) return \"empty\";\r\n if (states.some((s) => s === \"error\")) return \"error\";\r\n return \"initial\";\r\n}\r\n\r\n// ==================== Types ====================\r\ntype Padding = {\r\n l: string;\r\n r: string;\r\n t: string;\r\n b: string;\r\n};\r\n\r\ntype SnapPoint = number;\r\n\r\ntype SelectionState = \"loading\" | \"empty\" | \"error\" | \"data\" | \"initial\";\r\n\r\n\r\ntype TitleProps = {\r\n text: string;\r\n textColor: string;\r\n className?: string;\r\n containerClass?: string;\r\n style?: React.CSSProperties;\r\n};\r\n\r\ntype SearchProps = {\r\n text: string;\r\n textColor: string;\r\n className?: string;\r\n background?: string;\r\n prefixIcon?: React.ReactNode;\r\n suffixIcon?: React.ReactNode;\r\n clearIcon?: React.ReactNode;\r\n backIcon?: React.ReactNode;\r\n prefixGap?: string;\r\n suffixGap?: string;\r\n padding?: Padding;\r\n autoFocus?: boolean;\r\n inputStyle?: React.CSSProperties;\r\n containerStyle?: React.CSSProperties;\r\n onChange?: (value: string) => void;\r\n onFocus?: () => void;\r\n onBlur?: () => void;\r\n};\r\n\r\ntype LoadingProps = {\r\n view: React.ReactNode;\r\n padding?: Padding;\r\n style?: React.CSSProperties;\r\n};\r\n\r\ntype NoResultProps = {\r\n view: React.ReactNode;\r\n text?: string;\r\n padding?: Padding;\r\n style?: React.CSSProperties;\r\n};\r\n\r\ntype ErrorProps = {\r\n view: React.ReactNode;\r\n text?: string;\r\n padding?: Padding;\r\n style?: React.CSSProperties;\r\n};\r\n\r\ntype CancelButtonProps = {\r\n text?: string;\r\n view: React.ReactNode;\r\n position?: \"left\" | \"right\";\r\n style?: React.CSSProperties;\r\n onClick?: () => void;\r\n};\r\n\r\ntype LayoutProps = {\r\n gapBetweenHandleAndTitle?: string;\r\n gapBetweenTitleAndSearch?: string;\r\n gapBetweenSearchAndContent?: string;\r\n backgroundColor?: string;\r\n handleColor?: string;\r\n handleWidth?: string;\r\n fullScreenSearchBackground?: string;\r\n fullScreenSearchHeaderStyle?: React.CSSProperties;\r\n maxWidth?: string;\r\n};\r\n\r\ntype SelectionViewerProps = {\r\n id?: string;\r\n isOpen: boolean;\r\n backDrop?: boolean;\r\n onClose: () => void;\r\n titleProp: TitleProps;\r\n searchProp?: SearchProps;\r\n loadingProp?: LoadingProps;\r\n noResultProp?: NoResultProps;\r\n errorProp?: ErrorProps;\r\n cancelButton?: CancelButtonProps;\r\n layoutProp?: LayoutProps;\r\n childrenDirection?: \"vertical\" | \"horizontal\";\r\n children?: React.ReactNode;\r\n onPaginate?: () => boolean | Promise<boolean>;\r\n snapPoints?: SnapPoint[];\r\n initialSnap?: number;\r\n unmountOnClose?: boolean;\r\n zIndex?: number;\r\n /**\r\n * Accessible name for the sheet, announced when it opens.\r\n *\r\n * A modal with no name is announced simply as \"dialog\", which tells a screen-reader user that\r\n * something has taken over the screen and nothing at all about what.\r\n */\r\n ariaLabel?: string;\r\n maxHeight?: string;\r\n minHeight?: string;\r\n selectionState?: SelectionState;\r\n closeThreshold?: number;\r\n};\r\n\r\n// ==================== Styles ====================\r\nconst getStyles = (id: string) => `\r\n#${id} .selection-viewer-header {\r\n padding: 0px;\r\n display: flex;\r\n flex-direction: column;\r\n align-items: center;\r\n position: relative;\r\n width: 100%;\r\n}\r\n\r\n#${id} .selection-viewer-drag-handle {\r\n height: 5px;\r\n border-radius: 3px;\r\n margin-top: 16px;\r\n}\r\n\r\n#${id} .selection-viewer-container {\r\n display: flex;\r\n align-items: flex-start;\r\n width: 100%;\r\n}\r\n\r\n#${id} .selection-viewer-title {\r\n margin: 0px;\r\n font-size: 18px;\r\n font-weight: 600;\r\n padding: 0px 16px 0px 16px;\r\n word-break: break-word; /* break long words */\r\n white-space: normal; /* allow wrapping */\r\n}\r\n\r\n#${id} .selection-viewer-search {\r\n display: flex;\r\n align-items: center;\r\n margin: 16px 16px 4px 16px;\r\n border-radius: 12px;\r\n box-sizing: border-box;\r\n border: 1px solid rgba(0, 0, 0, 0.1);\r\n}\r\n\r\n#${id} .selection-viewer-search-input {\r\n flex: 1;\r\n border: none;\r\n background: transparent;\r\n padding: 12px 8px;\r\n outline: none;\r\n font-size: 16px !important;\r\n width: 100%;\r\n}\r\n\r\n#${id} .selection-viewer-content {\r\n overflow-y: auto;\r\n -webkit-overflow-scrolling: touch;\r\n flex: 1;\r\n min-height: 0;\r\n}\r\n\r\n#${id} .selection-viewer-content.vertical {\r\n display: flex;\r\n flex-direction: column;\r\n gap: 8px;\r\n}\r\n\r\n#${id} .selection-viewer-content.horizontal {\r\n display: flex;\r\n flex-direction: row;\r\n gap: 8px;\r\n overflow-x: auto;\r\n overflow-y: hidden;\r\n}\r\n\r\n#${id} .selection-viewer-no-results,\r\n#${id} .selection-viewer-error,\r\n#${id} .selection-viewer-loading {\r\n display: flex;\r\n justify-content: center;\r\n align-items: center;\r\n min-height: 120px;\r\n}\r\n\r\n#${id} .selection-viewer-default-no-results {\r\n color: #666;\r\n font-size: 14px;\r\n}\r\n\r\n#${id} .selection-viewer-default-error {\r\n color: red;\r\n font-size: 14px;\r\n}\r\n\r\n/* Full screen search mode */\r\n#${id} .selection-viewer-fullscreen-search {\r\n// position: fixed;\r\n top: 0;\r\n left: 0;\r\n right: 0;\r\n z-index: 10;\r\n// padding-top: env(safe-area-inset-top);\r\n width: 100%;\r\n}\r\n\r\n#${id} .selection-viewer-search-back-button {\r\n background: none;\r\n border: none;\r\n padding: 8px;\r\n margin-right: 4px;\r\n display: flex;\r\n align-items: center;\r\n justify-content: center;\r\n cursor: pointer;\r\n transition: opacity 0.2s;\r\n}\r\n\r\n#${id} .selection-viewer-search-back-button:hover {\r\n opacity: 0.7;\r\n}\r\n\r\n#${id} .selection-viewer-search-clear-button {\r\n background: none;\r\n border: none;\r\n padding: 8px;\r\n margin-left: 4px;\r\n display: flex;\r\n align-items: center;\r\n justify-content: center;\r\n cursor: pointer;\r\n transition: opacity 0.2s;\r\n}\r\n\r\n#${id} .selection-viewer-search-clear-button:hover {\r\n opacity: 0.7;\r\n}\r\n\r\n/* React Modal Sheet overrides */\r\n#${id} .react-modal-sheet-container {\r\n max-width: 500px;\r\n margin: 0 auto;\r\n border-top-left-radius: 16px;\r\n border-top-right-radius: 16px;\r\n}\r\n\r\n#${id} .react-modal-sheet-backdrop {\r\n background-color: rgba(0, 0, 0, 0.5) !important;\r\n pointer-events: auto !important;\r\n}\r\n\r\n#${id} .react-modal-sheet-content {\r\n padding: 0 0px 0px 0px;\r\n height: 100%;\r\n}\r\n\r\n\r\n/* Mobile full-width behavior */\r\n@media (max-width: 500px) {\r\n #${id} .react-modal-sheet-container {\r\n max-width: 100%;\r\n border-radius: 0;\r\n }\r\n}\r\n\r\n/* Prevent iOS zooming */\r\n@media screen and (-webkit-min-device-pixel-ratio: 0) {\r\n #${id} .selection-viewer-search-input {\r\n font-size: 16px !important;\r\n }\r\n}\r\n`;\r\n\r\n// ==================== Hook to inject CSS per instance ====================\r\nconst useInjectStyles = (id: string) => {\r\n useEffect(() => {\r\n const styleId = `selection-viewer-styles-${id}`;\r\n let styleTag = document.getElementById(styleId) as HTMLStyleElement | null;\r\n\r\n if (!styleTag) {\r\n styleTag = document.createElement(\"style\");\r\n styleTag.id = styleId;\r\n styleTag.innerHTML = getStyles(id);\r\n document.head.appendChild(styleTag);\r\n }\r\n\r\n // Cleanup on unmount\r\n return () => {\r\n if (styleTag && document.head.contains(styleTag)) {\r\n document.head.removeChild(styleTag);\r\n }\r\n };\r\n }, [id]);\r\n};\r\n\r\n// ==================== Component ====================\r\n/**\r\n * Escape closes the viewer, and Tab stays inside it.\r\n *\r\n * The viewer covers the screen, so what is behind it is not available — but nothing said so to the\r\n * keyboard. Tab walked out of the option list into the page underneath, where a person was\r\n * operating controls they could not see, and Escape did nothing at all, which is the one key\r\n * everybody reaches for to get out of a picker.\r\n *\r\n * Deliberately a private copy rather than an import from a sibling package: every library here\r\n * stands alone, and a shared helper between two of them is a dependency the consumer did not ask\r\n * for. Takes the container's `id` rather than a ref, because the sheet element belongs to the\r\n * underlying modal-sheet component; looking it up when a key is pressed finds it however that\r\n * component chooses to mount it. Focusables are re-queried on every Tab, since the option list\r\n * changes as the consumer filters it and a list captured on open is a list of dead elements.\r\n */\r\nconst useModalKeys = (isOpen: boolean, onClose: () => void, containerId: string) => {\r\n useEffect(() => {\r\n if (!isOpen || typeof document === \"undefined\") return;\r\n\r\n const onKeyDown = (e: KeyboardEvent) => {\r\n if (e.key === \"Escape\") {\r\n e.preventDefault();\r\n onClose();\r\n return;\r\n }\r\n if (e.key !== \"Tab\") return;\r\n\r\n const focusable = document.getElementById(containerId)?.querySelectorAll<HTMLElement>(\r\n 'a[href], button:not([disabled]), input:not([disabled]), select:not([disabled]),' +\r\n ' textarea:not([disabled]), [tabindex]:not([tabindex=\"-1\"])',\r\n );\r\n if (!focusable || focusable.length === 0) return;\r\n\r\n const first = focusable[0];\r\n const last = focusable[focusable.length - 1];\r\n\r\n if (e.shiftKey && document.activeElement === first) {\r\n e.preventDefault();\r\n last.focus();\r\n } else if (!e.shiftKey && document.activeElement === last) {\r\n e.preventDefault();\r\n first.focus();\r\n }\r\n };\r\n\r\n document.addEventListener(\"keydown\", onKeyDown);\r\n return () => document.removeEventListener(\"keydown\", onKeyDown);\r\n }, [isOpen, onClose, containerId]);\r\n};\r\n\r\nconst SelectionViewer: React.FC<SelectionViewerProps> = ({\r\n id: providedId,\r\n isOpen,\r\n backDrop = true,\r\n onClose,\r\n titleProp,\r\n searchProp,\r\n loadingProp,\r\n noResultProp,\r\n errorProp,\r\n cancelButton,\r\n layoutProp,\r\n childrenDirection = \"vertical\",\r\n children,\r\n onPaginate,\r\n snapPoints = [0, 1],\r\n initialSnap = 1,\r\n unmountOnClose = true,\r\n zIndex = 1000,\r\n ariaLabel,\r\n maxHeight = \"90dvh\",\r\n minHeight = \"65dvh\",\r\n selectionState: selectionStateProp = \"initial\",\r\n closeThreshold = 0.2,\r\n}) => {\r\n const [id] = useState(() => providedId || `selection-${Math.random().toString(36).substring(2, 11)}`);\r\n const [searchValue, setSearchValue] = useState(\"\");\r\n const [isSearchFocused, setIsSearchFocused] = useState(false);\r\n const [keyboardHeight, setKeyboardHeight] = useState(0);\r\n const [inputKey, setInputKey] = useState(0);\r\n const [shouldAutoFocus, setShouldAutoFocus] = useState(false);\r\n const isPaginating = useRef(false);\r\n const searchInputRef = useRef<HTMLInputElement>(null);\r\n const sheetRef = useRef<any>(null);\r\n const headerRef = useRef<HTMLDivElement>(null);\r\n\r\n useInjectStyles(id);\r\n // Escape closes the viewer and Tab stays inside it — see useModalKeys.\r\n useModalKeys(isOpen, onClose, id);\r\n\r\n // Descendant sections (a Column, or anything else) can report a cumulative state up through this —\r\n // starts empty, so a plain SelectionViewer with no Row/Column children behaves exactly as before.\r\n const [reportedStates, setReportedStates] = useState<Map<string, SelectionState>>(new Map());\r\n const reportAggregate = useCallback((reporterId: string, state: SelectionState) => {\r\n setReportedStates((prev) => {\r\n const next = new Map(prev);\r\n next.set(reporterId, state);\r\n return next;\r\n });\r\n }, []);\r\n const unreportAggregate = useCallback((reporterId: string) => {\r\n setReportedStates((prev) => {\r\n if (!prev.has(reporterId)) return prev;\r\n const next = new Map(prev);\r\n next.delete(reporterId);\r\n return next;\r\n });\r\n }, []);\r\n const aggregateReporterValue = useMemo(\r\n () => ({ report: reportAggregate, unreport: unreportAggregate }),\r\n [reportAggregate, unreportAggregate]\r\n );\r\n const reportedAggregate =\r\n reportedStates.size > 0 ? computeAggregateState(Array.from(reportedStates.values())) : null;\r\n const isComposed = reportedAggregate !== null;\r\n\r\n // Precedence: an explicit `selectionState` prop always wins (matches today's exact behaviour for\r\n // any consumer not using Row/Column) -> then a reported Column aggregate, if one exists -> \"initial\".\r\n const selectionState =\r\n selectionStateProp !== \"initial\" ? selectionStateProp : reportedAggregate ?? \"initial\";\r\n\r\n // Track keyboard height\r\n useEffect(() => {\r\n if (typeof window === 'undefined' || !window.visualViewport) return;\r\n\r\n const handleResize = () => {\r\n const vp = window.visualViewport!;\r\n const kbHeight = window.innerHeight - vp.height;\r\n setKeyboardHeight(kbHeight > 0 ? kbHeight : 0);\r\n };\r\n\r\n window.visualViewport.addEventListener('resize', handleResize);\r\n window.visualViewport.addEventListener('scroll', handleResize);\r\n\r\n return () => {\r\n window.visualViewport?.removeEventListener('resize', handleResize);\r\n window.visualViewport?.removeEventListener('scroll', handleResize);\r\n };\r\n }, []);\r\n\r\n // Auto-focus on search\r\n useEffect(() => {\r\n if (!isOpen) {\r\n searchInputRef.current?.blur();\r\n setSearchValue(\"\");\r\n searchProp?.onChange?.(\"\");\r\n setShouldAutoFocus(false);\r\n return;\r\n }\r\n }, [isOpen, searchProp?.autoFocus]);\r\n\r\n const handleOpenEnd = useCallback(() => {\r\n if (searchProp?.autoFocus && searchInputRef.current) {\r\n setInputKey(prev => prev + 1);\r\n setShouldAutoFocus(true);\r\n searchInputRef.current.focus();\r\n searchInputRef.current.click();\r\n }\r\n }, [searchProp?.autoFocus]);\r\n\r\n const handleSearchChange = (e: React.ChangeEvent<HTMLInputElement>) => {\r\n const value = e.target.value;\r\n setSearchValue(value);\r\n searchProp?.onChange?.(value);\r\n };\r\n\r\n const handleSearchFocus = () => {\r\n setIsSearchFocused(true);\r\n searchProp?.onFocus?.();\r\n requestAnimationFrame(() => {\r\n searchInputRef.current?.focus();\r\n });\r\n };\r\n\r\n const handleSearchBlur = () => {\r\n searchProp?.onBlur?.();\r\n };\r\n\r\n const handleBackFromSearch = () => {\r\n setIsSearchFocused(false);\r\n if (searchInputRef.current) {\r\n searchInputRef.current.blur();\r\n }\r\n };\r\n\r\n const clearSearch = () => {\r\n setSearchValue(\"\");\r\n searchProp?.onChange?.(\"\");\r\n if (searchInputRef.current) {\r\n searchInputRef.current.focus();\r\n }\r\n };\r\n\r\n const handleScroll = useCallback(\r\n async (e: React.UIEvent<HTMLDivElement>) => {\r\n if (isPaginating.current || !onPaginate) return;\r\n\r\n const { scrollTop, scrollHeight, clientHeight } = e.currentTarget;\r\n const isNearBottom = scrollHeight - scrollTop <= clientHeight * 1.2;\r\n\r\n if (isNearBottom) {\r\n isPaginating.current = true;\r\n const hasMore = await onPaginate();\r\n if (!hasMore) {\r\n isPaginating.current = false;\r\n } else {\r\n setTimeout(() => {\r\n isPaginating.current = false;\r\n }, 500);\r\n }\r\n }\r\n },\r\n [onPaginate]\r\n );\r\n\r\n if (!isOpen && unmountOnClose) return null;\r\n\r\n return (\r\n <SelectionViewerAggregateContext.Provider value={aggregateReporterValue}>\r\n <Sheet\r\n ref={sheetRef}\r\n isOpen={isOpen}\r\n onClose={onClose}\r\n detent=\"content\"\r\n style={{ zIndex }}\r\n maxHeight={maxHeight}\r\n onOpenEnd={handleOpenEnd}\r\n >\r\n <Sheet.Container\r\n id={id}\r\n // Announced as a modal dialog. Without this a screen reader reads the sheet as one more\r\n // region of the page and gives no indication that what is behind it is unavailable — and\r\n // an automated check for an open dialog finds nothing at all.\r\n role=\"dialog\"\r\n aria-modal=\"true\"\r\n aria-label={ariaLabel}\r\n style={{\r\n maxHeight: maxHeight,\r\n minHeight: isSearchFocused ? \"100dvh\" : minHeight,\r\n maxWidth: layoutProp?.maxWidth ?? '800px',\r\n margin: \"0 auto\",\r\n width: \"100%\",\r\n left: 0,\r\n right: 0,\r\n paddingBottom: \"calc(0px + env(safe-area-inset-bottom))\",\r\n background: isSearchFocused\r\n ? layoutProp?.fullScreenSearchBackground || layoutProp?.backgroundColor\r\n : layoutProp?.backgroundColor,\r\n borderTopLeftRadius: isSearchFocused ? \"0px\" : \"16px\",\r\n borderTopRightRadius: isSearchFocused ? \"0px\" : \"16px\",\r\n }}\r\n >\r\n {isSearchFocused ? (\r\n <Sheet.Header>\r\n <div\r\n className=\"selection-viewer-fullscreen-search\"\r\n style={layoutProp?.fullScreenSearchHeaderStyle}\r\n >\r\n <div className=\"selection-viewer-search\" style={{\r\n ...searchProp?.containerStyle,\r\n background: searchProp?.background,\r\n padding: searchProp?.padding\r\n ? `${searchProp.padding.t} ${searchProp.padding.r} ${searchProp.padding.b} ${searchProp.padding.l}`\r\n : \"16px\"\r\n }}>\r\n <button\r\n className=\"selection-viewer-search-back-button\"\r\n onClick={handleBackFromSearch}\r\n aria-label=\"Exit search mode\"\r\n >\r\n {searchProp?.backIcon || (\r\n <svg width=\"24\" height=\"24\" viewBox=\"0 0 24 24\" fill=\"none\" xmlns=\"http://www.w3.org/2000/svg\">\r\n <path d=\"M15 18L9 12L15 6\" stroke={searchProp?.textColor || 'currentColor'} strokeWidth=\"2\" strokeLinecap=\"round\" strokeLinejoin=\"round\" />\r\n </svg>\r\n )}\r\n </button>\r\n\r\n <input\r\n key={inputKey}\r\n ref={searchInputRef}\r\n type=\"text\"\r\n placeholder={searchProp?.text}\r\n value={searchValue}\r\n onChange={handleSearchChange}\r\n className={searchProp?.className || \"selection-viewer-search-input\"}\r\n style={{\r\n color: searchProp?.textColor,\r\n ...searchProp?.inputStyle\r\n }}\r\n onFocus={handleSearchFocus}\r\n onBlur={handleSearchBlur}\r\n autoFocus={shouldAutoFocus}\r\n />\r\n\r\n {searchValue && (\r\n <button\r\n className=\"selection-viewer-search-clear-button\"\r\n onClick={clearSearch}\r\n aria-label=\"Clear search\"\r\n >\r\n {searchProp?.clearIcon || (\r\n <svg width=\"24\" height=\"24\" viewBox=\"0 0 24 24\" fill=\"none\" xmlns=\"http://www.w3.org/2000/svg\">\r\n <path d=\"M18 6L6 18M6 6L18 18\" stroke={searchProp?.textColor || 'currentColor'} strokeWidth=\"2\" strokeLinecap=\"round\" strokeLinejoin=\"round\" />\r\n </svg>\r\n )}\r\n </button>\r\n )}\r\n </div>\r\n </div>\r\n </Sheet.Header>\r\n ) : (\r\n <Sheet.Header>\r\n <div className=\"selection-viewer-header\">\r\n {/* Cancel button left */}\r\n {cancelButton?.position === \"left\" && (\r\n <button\r\n style={{\r\n position: \"absolute\",\r\n left: \"0px\",\r\n top: \"8px\",\r\n border: \"none\",\r\n backgroundColor: \"transparent\",\r\n ...cancelButton.style\r\n }}\r\n onClick={cancelButton.onClick || onClose}\r\n >\r\n {cancelButton.view || cancelButton.text || \"Cancel\"}\r\n </button>\r\n )}\r\n\r\n {/* Drag handle */}\r\n {!isSearchFocused && (\r\n <div\r\n className=\"selection-viewer-drag-handle\"\r\n style={{\r\n background: layoutProp?.handleColor || \"#ccc\",\r\n width: layoutProp?.handleWidth || \"40px\",\r\n marginBottom: layoutProp?.gapBetweenHandleAndTitle || \"12px\",\r\n }}\r\n />\r\n )}\r\n\r\n {/* Cancel button right */}\r\n {cancelButton?.position === \"right\" && (\r\n <button\r\n style={{\r\n position: \"absolute\",\r\n right: \"0px\",\r\n top: \"8px\",\r\n border: \"none\",\r\n backgroundColor: \"transparent\",\r\n ...cancelButton.style\r\n }}\r\n onClick={cancelButton.onClick || onClose}\r\n >\r\n {cancelButton.view || cancelButton.text || \"Cancel\"}\r\n </button>\r\n )}\r\n\r\n {/* Title */}\r\n <div className={titleProp.containerClass || \"selection-viewer-container\"}>\r\n <h2\r\n id={`${id}-title`}\r\n className={titleProp.className || \"selection-viewer-title\"}\r\n style={{\r\n marginBottom: layoutProp?.gapBetweenTitleAndSearch || \"8px\",\r\n color: titleProp?.textColor || 'black',\r\n ...titleProp.style\r\n }}\r\n >\r\n {titleProp.text}\r\n </h2>\r\n </div>\r\n </div>\r\n\r\n {/* Search */}\r\n {searchProp && (\r\n <div\r\n className=\"selection-viewer-search\"\r\n style={{\r\n background: searchProp.background,\r\n padding: searchProp.padding\r\n ? `${searchProp.padding.t} ${searchProp.padding.r} ${searchProp.padding.b} ${searchProp.padding.l}`\r\n : \"8px 16px\",\r\n marginBottom: layoutProp?.gapBetweenSearchAndContent,\r\n ...searchProp.containerStyle\r\n }}\r\n >\r\n {searchProp.prefixIcon && (\r\n <span style={{ marginRight: searchProp.prefixGap || \"8px\" }}>\r\n {searchProp.prefixIcon}\r\n </span>\r\n )}\r\n <input\r\n key={inputKey}\r\n ref={searchInputRef}\r\n type=\"text\"\r\n placeholder={searchProp.text}\r\n value={searchValue}\r\n onChange={handleSearchChange}\r\n className={searchProp.className || \"selection-viewer-search-input\"}\r\n style={{\r\n color: searchProp?.textColor,\r\n ...searchProp.inputStyle\r\n }}\r\n onFocus={handleSearchFocus}\r\n onBlur={handleSearchBlur}\r\n autoFocus={shouldAutoFocus}\r\n />\r\n {searchValue && (\r\n <button\r\n className=\"selection-viewer-search-clear-button\"\r\n onClick={clearSearch}\r\n aria-label=\"Clear search\"\r\n style={{ marginLeft: searchProp.suffixGap || \"8px\" }}\r\n >\r\n {searchProp.clearIcon || searchProp.suffixIcon || (\r\n <svg width=\"24\" height=\"24\" viewBox=\"0 0 24 24\" fill=\"none\" xmlns=\"http://www.w3.org/2000/svg\">\r\n <path d=\"M18 6L6 18M6 6L18 18\" stroke=\"currentColor\" strokeWidth=\"2\" strokeLinecap=\"round\" strokeLinejoin=\"round\" />\r\n </svg>\r\n )}\r\n </button>\r\n )}\r\n {!searchValue && searchProp.suffixIcon && (\r\n <span style={{ marginLeft: searchProp.suffixGap || \"8px\" }}>\r\n {searchProp.suffixIcon}\r\n </span>\r\n )}\r\n </div>\r\n )}\r\n </Sheet.Header>\r\n )}\r\n\r\n <Sheet.Content>\r\n <div\r\n className={`selection-viewer-content ${childrenDirection}`}\r\n onScroll={onPaginate ? handleScroll : undefined}\r\n style={{\r\n paddingTop: isSearchFocused ? layoutProp?.gapBetweenSearchAndContent : '0',\r\n paddingBottom: keyboardHeight > 0\r\n ? `${keyboardHeight + 16}px`\r\n : '16px',\r\n }}\r\n >\r\n {/* Show children first, then loading at bottom */}\r\n {React.Children.count(children) > 0 ? (\r\n <>\r\n {children}\r\n {selectionState === \"loading\" && (\r\n <div\r\n className=\"selection-viewer-loading\"\r\n style={{\r\n padding: loadingProp?.padding\r\n ? `${loadingProp.padding.t} ${loadingProp.padding.r} ${loadingProp.padding.b} ${loadingProp.padding.l}`\r\n : \"16px\",\r\n ...loadingProp?.style\r\n }}\r\n >\r\n {loadingProp?.view}\r\n </div>\r\n )}\r\n {/* Composed mode: a Column/Row descendant reports its own state, which can only ever be\r\n \"empty\"/\"error\" here since the child count > 0 branch is unconditional on a literal\r\n <Column> being present. Layer the outer view alongside the (visually empty) children\r\n rather than replacing them — a Column/Row must stay mounted to keep reporting. */}\r\n {isComposed && selectionState === \"empty\" && (\r\n <div\r\n className=\"selection-viewer-no-results\"\r\n style={{\r\n padding: noResultProp?.padding\r\n ? `${noResultProp.padding.t} ${noResultProp.padding.r} ${noResultProp.padding.b} ${noResultProp.padding.l}`\r\n : \"16px\",\r\n ...noResultProp?.style\r\n }}\r\n >\r\n {noResultProp?.view || (\r\n <div className=\"selection-viewer-default-no-results\">\r\n {noResultProp?.text || \"No results found\"}\r\n </div>\r\n )}\r\n </div>\r\n )}\r\n {isComposed && selectionState === \"error\" && (\r\n <div\r\n className=\"selection-viewer-error\"\r\n style={{\r\n padding: errorProp?.padding\r\n ? `${errorProp.padding.t} ${errorProp.padding.r} ${errorProp.padding.b} ${errorProp.padding.l}`\r\n : \"16px\",\r\n ...errorProp?.style\r\n }}\r\n >\r\n {errorProp?.view || (\r\n <div className=\"selection-viewer-default-error\">\r\n {errorProp?.text || \"No results found\"}\r\n </div>\r\n )}\r\n </div>\r\n )}\r\n </>\r\n ) : (selectionState === \"empty\" || (React.Children.count(children) <= 0 && (selectionState != \"loading\" && selectionState != \"error\"))) ? (\r\n <div\r\n className=\"selection-viewer-no-results\"\r\n style={{\r\n padding: noResultProp?.padding\r\n ? `${noResultProp.padding.t} ${noResultProp.padding.r} ${noResultProp.padding.b} ${noResultProp.padding.l}`\r\n : \"16px\",\r\n ...noResultProp?.style\r\n }}\r\n >\r\n {noResultProp?.view || (\r\n <div className=\"selection-viewer-default-no-results\">\r\n {noResultProp?.text || \"No results found\"}\r\n </div>\r\n )}\r\n </div>\r\n ) : selectionState === \"loading\" ? (\r\n <div\r\n className=\"selection-viewer-loading\"\r\n style={{\r\n padding: loadingProp?.padding\r\n ? `${loadingProp.padding.t} ${loadingProp.padding.r} ${loadingProp.padding.b} ${loadingProp.padding.l}`\r\n : \"16px\",\r\n ...loadingProp?.style\r\n }}\r\n >\r\n {loadingProp?.view}\r\n </div>\r\n ) : (selectionState === \"error\") ? (\r\n <div\r\n className=\"selection-viewer-error\"\r\n style={{\r\n padding: errorProp?.padding\r\n ? `${errorProp.padding.t} ${errorProp.padding.r} ${errorProp.padding.b} ${errorProp.padding.l}`\r\n : \"16px\",\r\n ...errorProp?.style\r\n }}\r\n >\r\n {errorProp?.view || (\r\n <div className=\"selection-viewer-default-error\">\r\n {errorProp?.text || \"No results found\"}\r\n </div>\r\n )}\r\n </div>\r\n ) : null}\r\n </div>\r\n </Sheet.Content>\r\n </Sheet.Container>\r\n <Sheet.Backdrop onTap={backDrop ? onClose : undefined} />\r\n </Sheet>\r\n </SelectionViewerAggregateContext.Provider>\r\n );\r\n};\r\n\r\n// ==================== Controller Hook ====================\r\ntype Operation = {\r\n open: () => void;\r\n close: () => void;\r\n toggle: () => void;\r\n setSelectionState: (val: SelectionState) => void;\r\n};\r\n\r\nconst useSelectionController = (initialSelectionState?: SelectionState): [\r\n string,\r\n Operation,\r\n boolean,\r\n SelectionState\r\n] => {\r\n const [isOpen, setIsOpen] = useState(false);\r\n const [selectionState, setSelectionState] = useState(initialSelectionState || 'initial');\r\n const [selectionId] = useState(() => `selection-${Math.random().toString(36).substring(2, 11)}`);\r\n\r\n const operations = useMemo<Operation>(() => ({\r\n open: () => setIsOpen(true),\r\n close: () => setIsOpen(false),\r\n toggle: () => setIsOpen((prev) => !prev),\r\n setSelectionState\r\n }), [setSelectionState]);\r\n\r\n return [selectionId, operations, isOpen, selectionState];\r\n};\r\n\r\nexport { SelectionViewer, useSelectionController, RowAggregateContext, SelectionViewerAggregateContext, computeAggregateState };\r\nexport type {\r\n SelectionViewerProps,\r\n SelectionState,\r\n TitleProps,\r\n SearchProps,\r\n LoadingProps,\r\n NoResultProps,\r\n ErrorProps,\r\n CancelButtonProps,\r\n LayoutProps,\r\n Padding,\r\n SnapPoint,\r\n AggregateReporter,\r\n};\r\nexport default SelectionViewer;\r\n","import React, { useCallback, useEffect, useRef, useState } from \"react\";\nimport { RowAggregateContext } from \"./SelectionViewer\";\nimport type { SelectionState } from \"./SelectionViewer\";\n\nexport type RowProps = {\n id?: string;\n /** Consumer-owned — SelectionViewer has never owned fetch/filter state, so unlike\n * search-viewer's Row this isn't internally computed. Mirrors how `selectionState`\n * is already a prop on SelectionViewer itself today. Defaults to \"data\": if you\n * render children without wiring this, we assume what you rendered IS the data. */\n state?: SelectionState;\n /** Called when this Row is scrolled horizontally near its end. Return (or resolve to)\n * `true` if more data may follow (keeps the pagination trigger armed), `false` once\n * there's nothing left to fetch — mirrors SelectionViewer's own `onPaginate` contract. */\n onPaginate?: () => boolean | Promise<boolean>;\n className?: string;\n style?: React.CSSProperties;\n children?: React.ReactNode;\n};\n\n/** A horizontally-scrolling, independently-paginating section — the Row/Column\n * equivalent for `SelectionViewer`. No shared code with `@academix-admin/search-viewer`'s\n * Row (Library Charter: packages stay mutually independent) — this one has no\n * query/debounce/cache engine of its own since `SelectionViewer` never had one either;\n * the consumer owns fetching/filtering and just tells this Row what `state` it's in. */\nfunction Row({ id: providedId, state = \"data\", onPaginate, className, style, children }: RowProps) {\n const aggregateReporter = React.useContext(RowAggregateContext);\n const [rowId] = useState(() => providedId || `row-${Math.random().toString(36).substring(2, 11)}`);\n const containerRef = useRef<HTMLDivElement | null>(null);\n const isPaginating = useRef(false);\n\n const handleScroll = useCallback(async () => {\n const el = containerRef.current;\n if (!el || isPaginating.current || !onPaginate) return;\n\n // Same \"near the end\" threshold as SelectionViewer's own vertical pagination trigger, adapted\n // to horizontal scroll metrics since a Row scrolls sideways.\n const { scrollLeft, scrollWidth, clientWidth } = el;\n if (scrollWidth - scrollLeft > clientWidth * 1.2) return;\n\n isPaginating.current = true;\n const hasMore = await onPaginate();\n if (!hasMore) {\n isPaginating.current = false;\n } else {\n setTimeout(() => {\n isPaginating.current = false;\n }, 500);\n }\n }, [onPaginate]);\n\n useEffect(() => {\n const el = containerRef.current;\n if (!el || !onPaginate) return;\n el.addEventListener(\"scroll\", handleScroll);\n return () => el.removeEventListener(\"scroll\", handleScroll);\n }, [handleScroll, onPaginate]);\n\n useEffect(() => {\n aggregateReporter?.report(rowId, state);\n return () => aggregateReporter?.unreport(rowId);\n }, [aggregateReporter, rowId, state]);\n\n return (\n <div\n ref={containerRef}\n className={className ? `selection-viewer-row ${className}` : \"selection-viewer-row\"}\n style={{\n display: \"flex\",\n flexDirection: \"row\",\n gap: \"8px\",\n overflowX: \"auto\",\n overflowY: \"hidden\",\n ...style,\n }}\n >\n {children}\n </div>\n );\n}\n\nRow.displayName = \"Row\";\n\nexport { Row };\n","import React, { useCallback, useEffect, useMemo, useState } from \"react\";\nimport { RowAggregateContext, SelectionViewerAggregateContext, computeAggregateState } from \"./SelectionViewer\";\nimport type { SelectionState } from \"./SelectionViewer\";\n\nexport type ColumnProps = {\n id?: string;\n className?: string;\n style?: React.CSSProperties;\n children?: React.ReactNode;\n};\n\n/** A vertical arrangement of `Row`s (or other content) — the explicit, composable\n * equivalent of today's flat `children` list. Its default layout is deliberately\n * identical to the existing `.selection-viewer-content.vertical` rendering\n * (`flex-direction: column, gap: 8px`), so today's flat usage is, unchanged, \"an\n * implicit Column with no Rows.\"\n *\n * Provides the `RowAggregateContext` its `Row` children report into, computes ONE\n * cumulative state from everything reported, and is itself a reporter one level up:\n * nested inside another `Column` it reports through that Column's `RowAggregateContext`\n * (behaving like a Row); at the top level it reports through `SelectionViewerAggregateContext`,\n * which `SelectionViewer` provides — this drives the outer sheet's loading/empty/error\n * views automatically with zero manual wiring, and lets Columns nest arbitrarily deep. */\nfunction Column({ id: providedId, className, style, children }: ColumnProps) {\n const [columnId] = useState(\n () => providedId || `column-${Math.random().toString(36).substring(2, 11)}`\n );\n\n const [reportedStates, setReportedStates] = useState<Map<string, SelectionState>>(new Map());\n const report = useCallback((id: string, state: SelectionState) => {\n setReportedStates((prev) => {\n const next = new Map(prev);\n next.set(id, state);\n return next;\n });\n }, []);\n const unreport = useCallback((id: string) => {\n setReportedStates((prev) => {\n if (!prev.has(id)) return prev;\n const next = new Map(prev);\n next.delete(id);\n return next;\n });\n }, []);\n const rowAggregateValue = useMemo(() => ({ report, unreport }), [report, unreport]);\n\n const aggregateState =\n reportedStates.size > 0 ? computeAggregateState(Array.from(reportedStates.values())) : \"initial\";\n\n const parentRowAggregate = React.useContext(RowAggregateContext);\n const selectionViewerAggregate = React.useContext(SelectionViewerAggregateContext);\n const upstreamReporter = parentRowAggregate ?? selectionViewerAggregate;\n\n useEffect(() => {\n if (!upstreamReporter) return;\n upstreamReporter.report(columnId, aggregateState);\n return () => upstreamReporter.unreport(columnId);\n }, [upstreamReporter, columnId, aggregateState]);\n\n return (\n <RowAggregateContext.Provider value={rowAggregateValue}>\n <div\n className={className ? `selection-viewer-column ${className}` : \"selection-viewer-column\"}\n style={{ display: \"flex\", flexDirection: \"column\", gap: \"8px\", ...style }}\n >\n {children}\n </div>\n </RowAggregateContext.Provider>\n );\n}\n\nColumn.displayName = \"Column\";\n\nexport { Column };\n"]}
package/dist/index.d.cts CHANGED
@@ -98,6 +98,13 @@ type SelectionViewerProps = {
98
98
  initialSnap?: number;
99
99
  unmountOnClose?: boolean;
100
100
  zIndex?: number;
101
+ /**
102
+ * Accessible name for the sheet, announced when it opens.
103
+ *
104
+ * A modal with no name is announced simply as "dialog", which tells a screen-reader user that
105
+ * something has taken over the screen and nothing at all about what.
106
+ */
107
+ ariaLabel?: string;
101
108
  maxHeight?: string;
102
109
  minHeight?: string;
103
110
  selectionState?: SelectionState;
package/dist/index.d.ts CHANGED
@@ -98,6 +98,13 @@ type SelectionViewerProps = {
98
98
  initialSnap?: number;
99
99
  unmountOnClose?: boolean;
100
100
  zIndex?: number;
101
+ /**
102
+ * Accessible name for the sheet, announced when it opens.
103
+ *
104
+ * A modal with no name is announced simply as "dialog", which tells a screen-reader user that
105
+ * something has taken over the screen and nothing at all about what.
106
+ */
107
+ ariaLabel?: string;
101
108
  maxHeight?: string;
102
109
  minHeight?: string;
103
110
  selectionState?: SelectionState;
package/dist/index.js CHANGED
@@ -198,6 +198,34 @@ var useInjectStyles = (id) => {
198
198
  };
199
199
  }, [id]);
200
200
  };
201
+ var useModalKeys = (isOpen, onClose, containerId) => {
202
+ useEffect(() => {
203
+ if (!isOpen || typeof document === "undefined") return;
204
+ const onKeyDown = (e) => {
205
+ if (e.key === "Escape") {
206
+ e.preventDefault();
207
+ onClose();
208
+ return;
209
+ }
210
+ if (e.key !== "Tab") return;
211
+ const focusable = document.getElementById(containerId)?.querySelectorAll(
212
+ 'a[href], button:not([disabled]), input:not([disabled]), select:not([disabled]), textarea:not([disabled]), [tabindex]:not([tabindex="-1"])'
213
+ );
214
+ if (!focusable || focusable.length === 0) return;
215
+ const first = focusable[0];
216
+ const last = focusable[focusable.length - 1];
217
+ if (e.shiftKey && document.activeElement === first) {
218
+ e.preventDefault();
219
+ last.focus();
220
+ } else if (!e.shiftKey && document.activeElement === last) {
221
+ e.preventDefault();
222
+ first.focus();
223
+ }
224
+ };
225
+ document.addEventListener("keydown", onKeyDown);
226
+ return () => document.removeEventListener("keydown", onKeyDown);
227
+ }, [isOpen, onClose, containerId]);
228
+ };
201
229
  var SelectionViewer = ({
202
230
  id: providedId,
203
231
  isOpen,
@@ -217,6 +245,7 @@ var SelectionViewer = ({
217
245
  initialSnap = 1,
218
246
  unmountOnClose = true,
219
247
  zIndex = 1e3,
248
+ ariaLabel,
220
249
  maxHeight = "90dvh",
221
250
  minHeight = "65dvh",
222
251
  selectionState: selectionStateProp = "initial",
@@ -233,6 +262,7 @@ var SelectionViewer = ({
233
262
  const sheetRef = useRef(null);
234
263
  useRef(null);
235
264
  useInjectStyles(id);
265
+ useModalKeys(isOpen, onClose, id);
236
266
  const [reportedStates, setReportedStates] = useState(/* @__PURE__ */ new Map());
237
267
  const reportAggregate = useCallback((reporterId, state) => {
238
268
  setReportedStates((prev) => {
@@ -350,6 +380,9 @@ var SelectionViewer = ({
350
380
  Sheet.Container,
351
381
  {
352
382
  id,
383
+ role: "dialog",
384
+ "aria-modal": "true",
385
+ "aria-label": ariaLabel,
353
386
  style: {
354
387
  maxHeight,
355
388
  minHeight: isSearchFocused ? "100dvh" : minHeight,
package/dist/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/SelectionViewer.tsx","../src/Row.tsx","../src/Column.tsx"],"names":["React","useState","useRef","useCallback","useEffect","jsx","useMemo"],"mappings":"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","file":"index.js","sourcesContent":["import React, { useState, useEffect, useCallback, useRef, useMemo } from \"react\";\nimport { Sheet } from \"@academix-admin/modal-sheet\";\n\n// ==================== Aggregation (Row/Column) ====================\n// Independent from @academix-admin/search-viewer's equivalent (Library Charter: packages stay\n// mutually independent) — same shape, duplicated intentionally rather than shared.\n\ntype AggregateReporter = {\n report: (id: string, state: SelectionState) => void;\n unreport: (id: string) => void;\n};\n\n/** A `Row` reports its own `state` into the nearest `Column` through this. */\nconst RowAggregateContext = React.createContext<AggregateReporter | null>(null);\n\n/** `Column` reports its own aggregated state up through this — `SelectionViewer` provides it and\n * merges whatever's reported into its own selectionState resolution, with zero extra wiring. */\nconst SelectionViewerAggregateContext = React.createContext<AggregateReporter | null>(null);\n\nfunction computeAggregateState(states: SelectionState[]): SelectionState {\n if (states.length === 0) return \"initial\";\n if (states.some((s) => s === \"data\")) return \"data\";\n if (states.some((s) => s === \"loading\")) return \"loading\";\n if (states.every((s) => s === \"empty\")) return \"empty\";\n if (states.some((s) => s === \"error\")) return \"error\";\n return \"initial\";\n}\n\n// ==================== Types ====================\ntype Padding = {\n l: string;\n r: string;\n t: string;\n b: string;\n};\n\ntype SnapPoint = number;\n\ntype SelectionState = \"loading\" | \"empty\" | \"error\" | \"data\" | \"initial\";\n\n\ntype TitleProps = {\n text: string;\n textColor: string;\n className?: string;\n containerClass?: string;\n style?: React.CSSProperties;\n};\n\ntype SearchProps = {\n text: string;\n textColor: string;\n className?: string;\n background?: string;\n prefixIcon?: React.ReactNode;\n suffixIcon?: React.ReactNode;\n clearIcon?: React.ReactNode;\n backIcon?: React.ReactNode;\n prefixGap?: string;\n suffixGap?: string;\n padding?: Padding;\n autoFocus?: boolean;\n inputStyle?: React.CSSProperties;\n containerStyle?: React.CSSProperties;\n onChange?: (value: string) => void;\n onFocus?: () => void;\n onBlur?: () => void;\n};\n\ntype LoadingProps = {\n view: React.ReactNode;\n padding?: Padding;\n style?: React.CSSProperties;\n};\n\ntype NoResultProps = {\n view: React.ReactNode;\n text?: string;\n padding?: Padding;\n style?: React.CSSProperties;\n};\n\ntype ErrorProps = {\n view: React.ReactNode;\n text?: string;\n padding?: Padding;\n style?: React.CSSProperties;\n};\n\ntype CancelButtonProps = {\n text?: string;\n view: React.ReactNode;\n position?: \"left\" | \"right\";\n style?: React.CSSProperties;\n onClick?: () => void;\n};\n\ntype LayoutProps = {\n gapBetweenHandleAndTitle?: string;\n gapBetweenTitleAndSearch?: string;\n gapBetweenSearchAndContent?: string;\n backgroundColor?: string;\n handleColor?: string;\n handleWidth?: string;\n fullScreenSearchBackground?: string;\n fullScreenSearchHeaderStyle?: React.CSSProperties;\n maxWidth?: string;\n};\n\ntype SelectionViewerProps = {\n id?: string;\n isOpen: boolean;\n backDrop?: boolean;\n onClose: () => void;\n titleProp: TitleProps;\n searchProp?: SearchProps;\n loadingProp?: LoadingProps;\n noResultProp?: NoResultProps;\n errorProp?: ErrorProps;\n cancelButton?: CancelButtonProps;\n layoutProp?: LayoutProps;\n childrenDirection?: \"vertical\" | \"horizontal\";\n children?: React.ReactNode;\n onPaginate?: () => boolean | Promise<boolean>;\n snapPoints?: SnapPoint[];\n initialSnap?: number;\n unmountOnClose?: boolean;\n zIndex?: number;\n maxHeight?: string;\n minHeight?: string;\n selectionState?: SelectionState;\n closeThreshold?: number;\n};\n\n// ==================== Styles ====================\nconst getStyles = (id: string) => `\n#${id} .selection-viewer-header {\n padding: 0px;\n display: flex;\n flex-direction: column;\n align-items: center;\n position: relative;\n width: 100%;\n}\n\n#${id} .selection-viewer-drag-handle {\n height: 5px;\n border-radius: 3px;\n margin-top: 16px;\n}\n\n#${id} .selection-viewer-container {\n display: flex;\n align-items: flex-start;\n width: 100%;\n}\n\n#${id} .selection-viewer-title {\n margin: 0px;\n font-size: 18px;\n font-weight: 600;\n padding: 0px 16px 0px 16px;\n word-break: break-word; /* break long words */\n white-space: normal; /* allow wrapping */\n}\n\n#${id} .selection-viewer-search {\n display: flex;\n align-items: center;\n margin: 16px 16px 4px 16px;\n border-radius: 12px;\n box-sizing: border-box;\n border: 1px solid rgba(0, 0, 0, 0.1);\n}\n\n#${id} .selection-viewer-search-input {\n flex: 1;\n border: none;\n background: transparent;\n padding: 12px 8px;\n outline: none;\n font-size: 16px !important;\n width: 100%;\n}\n\n#${id} .selection-viewer-content {\n overflow-y: auto;\n -webkit-overflow-scrolling: touch;\n flex: 1;\n min-height: 0;\n}\n\n#${id} .selection-viewer-content.vertical {\n display: flex;\n flex-direction: column;\n gap: 8px;\n}\n\n#${id} .selection-viewer-content.horizontal {\n display: flex;\n flex-direction: row;\n gap: 8px;\n overflow-x: auto;\n overflow-y: hidden;\n}\n\n#${id} .selection-viewer-no-results,\n#${id} .selection-viewer-error,\n#${id} .selection-viewer-loading {\n display: flex;\n justify-content: center;\n align-items: center;\n min-height: 120px;\n}\n\n#${id} .selection-viewer-default-no-results {\n color: #666;\n font-size: 14px;\n}\n\n#${id} .selection-viewer-default-error {\n color: red;\n font-size: 14px;\n}\n\n/* Full screen search mode */\n#${id} .selection-viewer-fullscreen-search {\n// position: fixed;\n top: 0;\n left: 0;\n right: 0;\n z-index: 10;\n// padding-top: env(safe-area-inset-top);\n width: 100%;\n}\n\n#${id} .selection-viewer-search-back-button {\n background: none;\n border: none;\n padding: 8px;\n margin-right: 4px;\n display: flex;\n align-items: center;\n justify-content: center;\n cursor: pointer;\n transition: opacity 0.2s;\n}\n\n#${id} .selection-viewer-search-back-button:hover {\n opacity: 0.7;\n}\n\n#${id} .selection-viewer-search-clear-button {\n background: none;\n border: none;\n padding: 8px;\n margin-left: 4px;\n display: flex;\n align-items: center;\n justify-content: center;\n cursor: pointer;\n transition: opacity 0.2s;\n}\n\n#${id} .selection-viewer-search-clear-button:hover {\n opacity: 0.7;\n}\n\n/* React Modal Sheet overrides */\n#${id} .react-modal-sheet-container {\n max-width: 500px;\n margin: 0 auto;\n border-top-left-radius: 16px;\n border-top-right-radius: 16px;\n}\n\n#${id} .react-modal-sheet-backdrop {\n background-color: rgba(0, 0, 0, 0.5) !important;\n pointer-events: auto !important;\n}\n\n#${id} .react-modal-sheet-content {\n padding: 0 0px 0px 0px;\n height: 100%;\n}\n\n\n/* Mobile full-width behavior */\n@media (max-width: 500px) {\n #${id} .react-modal-sheet-container {\n max-width: 100%;\n border-radius: 0;\n }\n}\n\n/* Prevent iOS zooming */\n@media screen and (-webkit-min-device-pixel-ratio: 0) {\n #${id} .selection-viewer-search-input {\n font-size: 16px !important;\n }\n}\n`;\n\n// ==================== Hook to inject CSS per instance ====================\nconst useInjectStyles = (id: string) => {\n useEffect(() => {\n const styleId = `selection-viewer-styles-${id}`;\n let styleTag = document.getElementById(styleId) as HTMLStyleElement | null;\n\n if (!styleTag) {\n styleTag = document.createElement(\"style\");\n styleTag.id = styleId;\n styleTag.innerHTML = getStyles(id);\n document.head.appendChild(styleTag);\n }\n\n // Cleanup on unmount\n return () => {\n if (styleTag && document.head.contains(styleTag)) {\n document.head.removeChild(styleTag);\n }\n };\n }, [id]);\n};\n\n// ==================== Component ====================\nconst SelectionViewer: React.FC<SelectionViewerProps> = ({\n id: providedId,\n isOpen,\n backDrop = true,\n onClose,\n titleProp,\n searchProp,\n loadingProp,\n noResultProp,\n errorProp,\n cancelButton,\n layoutProp,\n childrenDirection = \"vertical\",\n children,\n onPaginate,\n snapPoints = [0, 1],\n initialSnap = 1,\n unmountOnClose = true,\n zIndex = 1000,\n maxHeight = \"90dvh\",\n minHeight = \"65dvh\",\n selectionState: selectionStateProp = \"initial\",\n closeThreshold = 0.2,\n}) => {\n const [id] = useState(() => providedId || `selection-${Math.random().toString(36).substring(2, 11)}`);\n const [searchValue, setSearchValue] = useState(\"\");\n const [isSearchFocused, setIsSearchFocused] = useState(false);\n const [keyboardHeight, setKeyboardHeight] = useState(0);\n const [inputKey, setInputKey] = useState(0);\n const [shouldAutoFocus, setShouldAutoFocus] = useState(false);\n const isPaginating = useRef(false);\n const searchInputRef = useRef<HTMLInputElement>(null);\n const sheetRef = useRef<any>(null);\n const headerRef = useRef<HTMLDivElement>(null);\n\n useInjectStyles(id);\n\n // Descendant sections (a Column, or anything else) can report a cumulative state up through this —\n // starts empty, so a plain SelectionViewer with no Row/Column children behaves exactly as before.\n const [reportedStates, setReportedStates] = useState<Map<string, SelectionState>>(new Map());\n const reportAggregate = useCallback((reporterId: string, state: SelectionState) => {\n setReportedStates((prev) => {\n const next = new Map(prev);\n next.set(reporterId, state);\n return next;\n });\n }, []);\n const unreportAggregate = useCallback((reporterId: string) => {\n setReportedStates((prev) => {\n if (!prev.has(reporterId)) return prev;\n const next = new Map(prev);\n next.delete(reporterId);\n return next;\n });\n }, []);\n const aggregateReporterValue = useMemo(\n () => ({ report: reportAggregate, unreport: unreportAggregate }),\n [reportAggregate, unreportAggregate]\n );\n const reportedAggregate =\n reportedStates.size > 0 ? computeAggregateState(Array.from(reportedStates.values())) : null;\n const isComposed = reportedAggregate !== null;\n\n // Precedence: an explicit `selectionState` prop always wins (matches today's exact behaviour for\n // any consumer not using Row/Column) -> then a reported Column aggregate, if one exists -> \"initial\".\n const selectionState =\n selectionStateProp !== \"initial\" ? selectionStateProp : reportedAggregate ?? \"initial\";\n\n // Track keyboard height\n useEffect(() => {\n if (typeof window === 'undefined' || !window.visualViewport) return;\n\n const handleResize = () => {\n const vp = window.visualViewport!;\n const kbHeight = window.innerHeight - vp.height;\n setKeyboardHeight(kbHeight > 0 ? kbHeight : 0);\n };\n\n window.visualViewport.addEventListener('resize', handleResize);\n window.visualViewport.addEventListener('scroll', handleResize);\n\n return () => {\n window.visualViewport?.removeEventListener('resize', handleResize);\n window.visualViewport?.removeEventListener('scroll', handleResize);\n };\n }, []);\n\n // Auto-focus on search\n useEffect(() => {\n if (!isOpen) {\n searchInputRef.current?.blur();\n setSearchValue(\"\");\n searchProp?.onChange?.(\"\");\n setShouldAutoFocus(false);\n return;\n }\n }, [isOpen, searchProp?.autoFocus]);\n\n const handleOpenEnd = useCallback(() => {\n if (searchProp?.autoFocus && searchInputRef.current) {\n setInputKey(prev => prev + 1);\n setShouldAutoFocus(true);\n searchInputRef.current.focus();\n searchInputRef.current.click();\n }\n }, [searchProp?.autoFocus]);\n\n const handleSearchChange = (e: React.ChangeEvent<HTMLInputElement>) => {\n const value = e.target.value;\n setSearchValue(value);\n searchProp?.onChange?.(value);\n };\n\n const handleSearchFocus = () => {\n setIsSearchFocused(true);\n searchProp?.onFocus?.();\n requestAnimationFrame(() => {\n searchInputRef.current?.focus();\n });\n };\n\n const handleSearchBlur = () => {\n searchProp?.onBlur?.();\n };\n\n const handleBackFromSearch = () => {\n setIsSearchFocused(false);\n if (searchInputRef.current) {\n searchInputRef.current.blur();\n }\n };\n\n const clearSearch = () => {\n setSearchValue(\"\");\n searchProp?.onChange?.(\"\");\n if (searchInputRef.current) {\n searchInputRef.current.focus();\n }\n };\n\n const handleScroll = useCallback(\n async (e: React.UIEvent<HTMLDivElement>) => {\n if (isPaginating.current || !onPaginate) return;\n\n const { scrollTop, scrollHeight, clientHeight } = e.currentTarget;\n const isNearBottom = scrollHeight - scrollTop <= clientHeight * 1.2;\n\n if (isNearBottom) {\n isPaginating.current = true;\n const hasMore = await onPaginate();\n if (!hasMore) {\n isPaginating.current = false;\n } else {\n setTimeout(() => {\n isPaginating.current = false;\n }, 500);\n }\n }\n },\n [onPaginate]\n );\n\n if (!isOpen && unmountOnClose) return null;\n\n return (\n <SelectionViewerAggregateContext.Provider value={aggregateReporterValue}>\n <Sheet\n ref={sheetRef}\n isOpen={isOpen}\n onClose={onClose}\n detent=\"content\"\n style={{ zIndex }}\n maxHeight={maxHeight}\n onOpenEnd={handleOpenEnd}\n >\n <Sheet.Container\n id={id}\n style={{\n maxHeight: maxHeight,\n minHeight: isSearchFocused ? \"100dvh\" : minHeight,\n maxWidth: layoutProp?.maxWidth ?? '800px',\n margin: \"0 auto\",\n width: \"100%\",\n left: 0,\n right: 0,\n paddingBottom: \"calc(0px + env(safe-area-inset-bottom))\",\n background: isSearchFocused\n ? layoutProp?.fullScreenSearchBackground || layoutProp?.backgroundColor\n : layoutProp?.backgroundColor,\n borderTopLeftRadius: isSearchFocused ? \"0px\" : \"16px\",\n borderTopRightRadius: isSearchFocused ? \"0px\" : \"16px\",\n }}\n >\n {isSearchFocused ? (\n <Sheet.Header>\n <div\n className=\"selection-viewer-fullscreen-search\"\n style={layoutProp?.fullScreenSearchHeaderStyle}\n >\n <div className=\"selection-viewer-search\" style={{\n ...searchProp?.containerStyle,\n background: searchProp?.background,\n padding: searchProp?.padding\n ? `${searchProp.padding.t} ${searchProp.padding.r} ${searchProp.padding.b} ${searchProp.padding.l}`\n : \"16px\"\n }}>\n <button\n className=\"selection-viewer-search-back-button\"\n onClick={handleBackFromSearch}\n aria-label=\"Exit search mode\"\n >\n {searchProp?.backIcon || (\n <svg width=\"24\" height=\"24\" viewBox=\"0 0 24 24\" fill=\"none\" xmlns=\"http://www.w3.org/2000/svg\">\n <path d=\"M15 18L9 12L15 6\" stroke={searchProp?.textColor || 'currentColor'} strokeWidth=\"2\" strokeLinecap=\"round\" strokeLinejoin=\"round\" />\n </svg>\n )}\n </button>\n\n <input\n key={inputKey}\n ref={searchInputRef}\n type=\"text\"\n placeholder={searchProp?.text}\n value={searchValue}\n onChange={handleSearchChange}\n className={searchProp?.className || \"selection-viewer-search-input\"}\n style={{\n color: searchProp?.textColor,\n ...searchProp?.inputStyle\n }}\n onFocus={handleSearchFocus}\n onBlur={handleSearchBlur}\n autoFocus={shouldAutoFocus}\n />\n\n {searchValue && (\n <button\n className=\"selection-viewer-search-clear-button\"\n onClick={clearSearch}\n aria-label=\"Clear search\"\n >\n {searchProp?.clearIcon || (\n <svg width=\"24\" height=\"24\" viewBox=\"0 0 24 24\" fill=\"none\" xmlns=\"http://www.w3.org/2000/svg\">\n <path d=\"M18 6L6 18M6 6L18 18\" stroke={searchProp?.textColor || 'currentColor'} strokeWidth=\"2\" strokeLinecap=\"round\" strokeLinejoin=\"round\" />\n </svg>\n )}\n </button>\n )}\n </div>\n </div>\n </Sheet.Header>\n ) : (\n <Sheet.Header>\n <div className=\"selection-viewer-header\">\n {/* Cancel button left */}\n {cancelButton?.position === \"left\" && (\n <button\n style={{\n position: \"absolute\",\n left: \"0px\",\n top: \"8px\",\n border: \"none\",\n backgroundColor: \"transparent\",\n ...cancelButton.style\n }}\n onClick={cancelButton.onClick || onClose}\n >\n {cancelButton.view || cancelButton.text || \"Cancel\"}\n </button>\n )}\n\n {/* Drag handle */}\n {!isSearchFocused && (\n <div\n className=\"selection-viewer-drag-handle\"\n style={{\n background: layoutProp?.handleColor || \"#ccc\",\n width: layoutProp?.handleWidth || \"40px\",\n marginBottom: layoutProp?.gapBetweenHandleAndTitle || \"12px\",\n }}\n />\n )}\n\n {/* Cancel button right */}\n {cancelButton?.position === \"right\" && (\n <button\n style={{\n position: \"absolute\",\n right: \"0px\",\n top: \"8px\",\n border: \"none\",\n backgroundColor: \"transparent\",\n ...cancelButton.style\n }}\n onClick={cancelButton.onClick || onClose}\n >\n {cancelButton.view || cancelButton.text || \"Cancel\"}\n </button>\n )}\n\n {/* Title */}\n <div className={titleProp.containerClass || \"selection-viewer-container\"}>\n <h2\n id={`${id}-title`}\n className={titleProp.className || \"selection-viewer-title\"}\n style={{\n marginBottom: layoutProp?.gapBetweenTitleAndSearch || \"8px\",\n color: titleProp?.textColor || 'black',\n ...titleProp.style\n }}\n >\n {titleProp.text}\n </h2>\n </div>\n </div>\n\n {/* Search */}\n {searchProp && (\n <div\n className=\"selection-viewer-search\"\n style={{\n background: searchProp.background,\n padding: searchProp.padding\n ? `${searchProp.padding.t} ${searchProp.padding.r} ${searchProp.padding.b} ${searchProp.padding.l}`\n : \"8px 16px\",\n marginBottom: layoutProp?.gapBetweenSearchAndContent,\n ...searchProp.containerStyle\n }}\n >\n {searchProp.prefixIcon && (\n <span style={{ marginRight: searchProp.prefixGap || \"8px\" }}>\n {searchProp.prefixIcon}\n </span>\n )}\n <input\n key={inputKey}\n ref={searchInputRef}\n type=\"text\"\n placeholder={searchProp.text}\n value={searchValue}\n onChange={handleSearchChange}\n className={searchProp.className || \"selection-viewer-search-input\"}\n style={{\n color: searchProp?.textColor,\n ...searchProp.inputStyle\n }}\n onFocus={handleSearchFocus}\n onBlur={handleSearchBlur}\n autoFocus={shouldAutoFocus}\n />\n {searchValue && (\n <button\n className=\"selection-viewer-search-clear-button\"\n onClick={clearSearch}\n aria-label=\"Clear search\"\n style={{ marginLeft: searchProp.suffixGap || \"8px\" }}\n >\n {searchProp.clearIcon || searchProp.suffixIcon || (\n <svg width=\"24\" height=\"24\" viewBox=\"0 0 24 24\" fill=\"none\" xmlns=\"http://www.w3.org/2000/svg\">\n <path d=\"M18 6L6 18M6 6L18 18\" stroke=\"currentColor\" strokeWidth=\"2\" strokeLinecap=\"round\" strokeLinejoin=\"round\" />\n </svg>\n )}\n </button>\n )}\n {!searchValue && searchProp.suffixIcon && (\n <span style={{ marginLeft: searchProp.suffixGap || \"8px\" }}>\n {searchProp.suffixIcon}\n </span>\n )}\n </div>\n )}\n </Sheet.Header>\n )}\n\n <Sheet.Content>\n <div\n className={`selection-viewer-content ${childrenDirection}`}\n onScroll={onPaginate ? handleScroll : undefined}\n style={{\n paddingTop: isSearchFocused ? layoutProp?.gapBetweenSearchAndContent : '0',\n paddingBottom: keyboardHeight > 0\n ? `${keyboardHeight + 16}px`\n : '16px',\n }}\n >\n {/* Show children first, then loading at bottom */}\n {React.Children.count(children) > 0 ? (\n <>\n {children}\n {selectionState === \"loading\" && (\n <div\n className=\"selection-viewer-loading\"\n style={{\n padding: loadingProp?.padding\n ? `${loadingProp.padding.t} ${loadingProp.padding.r} ${loadingProp.padding.b} ${loadingProp.padding.l}`\n : \"16px\",\n ...loadingProp?.style\n }}\n >\n {loadingProp?.view}\n </div>\n )}\n {/* Composed mode: a Column/Row descendant reports its own state, which can only ever be\n \"empty\"/\"error\" here since the child count > 0 branch is unconditional on a literal\n <Column> being present. Layer the outer view alongside the (visually empty) children\n rather than replacing them — a Column/Row must stay mounted to keep reporting. */}\n {isComposed && selectionState === \"empty\" && (\n <div\n className=\"selection-viewer-no-results\"\n style={{\n padding: noResultProp?.padding\n ? `${noResultProp.padding.t} ${noResultProp.padding.r} ${noResultProp.padding.b} ${noResultProp.padding.l}`\n : \"16px\",\n ...noResultProp?.style\n }}\n >\n {noResultProp?.view || (\n <div className=\"selection-viewer-default-no-results\">\n {noResultProp?.text || \"No results found\"}\n </div>\n )}\n </div>\n )}\n {isComposed && selectionState === \"error\" && (\n <div\n className=\"selection-viewer-error\"\n style={{\n padding: errorProp?.padding\n ? `${errorProp.padding.t} ${errorProp.padding.r} ${errorProp.padding.b} ${errorProp.padding.l}`\n : \"16px\",\n ...errorProp?.style\n }}\n >\n {errorProp?.view || (\n <div className=\"selection-viewer-default-error\">\n {errorProp?.text || \"No results found\"}\n </div>\n )}\n </div>\n )}\n </>\n ) : (selectionState === \"empty\" || (React.Children.count(children) <= 0 && (selectionState != \"loading\" && selectionState != \"error\"))) ? (\n <div\n className=\"selection-viewer-no-results\"\n style={{\n padding: noResultProp?.padding\n ? `${noResultProp.padding.t} ${noResultProp.padding.r} ${noResultProp.padding.b} ${noResultProp.padding.l}`\n : \"16px\",\n ...noResultProp?.style\n }}\n >\n {noResultProp?.view || (\n <div className=\"selection-viewer-default-no-results\">\n {noResultProp?.text || \"No results found\"}\n </div>\n )}\n </div>\n ) : selectionState === \"loading\" ? (\n <div\n className=\"selection-viewer-loading\"\n style={{\n padding: loadingProp?.padding\n ? `${loadingProp.padding.t} ${loadingProp.padding.r} ${loadingProp.padding.b} ${loadingProp.padding.l}`\n : \"16px\",\n ...loadingProp?.style\n }}\n >\n {loadingProp?.view}\n </div>\n ) : (selectionState === \"error\") ? (\n <div\n className=\"selection-viewer-error\"\n style={{\n padding: errorProp?.padding\n ? `${errorProp.padding.t} ${errorProp.padding.r} ${errorProp.padding.b} ${errorProp.padding.l}`\n : \"16px\",\n ...errorProp?.style\n }}\n >\n {errorProp?.view || (\n <div className=\"selection-viewer-default-error\">\n {errorProp?.text || \"No results found\"}\n </div>\n )}\n </div>\n ) : null}\n </div>\n </Sheet.Content>\n </Sheet.Container>\n <Sheet.Backdrop onTap={backDrop ? onClose : undefined} />\n </Sheet>\n </SelectionViewerAggregateContext.Provider>\n );\n};\n\n// ==================== Controller Hook ====================\ntype Operation = {\n open: () => void;\n close: () => void;\n toggle: () => void;\n setSelectionState: (val: SelectionState) => void;\n};\n\nconst useSelectionController = (initialSelectionState?: SelectionState): [\n string,\n Operation,\n boolean,\n SelectionState\n] => {\n const [isOpen, setIsOpen] = useState(false);\n const [selectionState, setSelectionState] = useState(initialSelectionState || 'initial');\n const [selectionId] = useState(() => `selection-${Math.random().toString(36).substring(2, 11)}`);\n\n const operations = useMemo<Operation>(() => ({\n open: () => setIsOpen(true),\n close: () => setIsOpen(false),\n toggle: () => setIsOpen((prev) => !prev),\n setSelectionState\n }), [setSelectionState]);\n\n return [selectionId, operations, isOpen, selectionState];\n};\n\nexport { SelectionViewer, useSelectionController, RowAggregateContext, SelectionViewerAggregateContext, computeAggregateState };\nexport type {\n SelectionViewerProps,\n SelectionState,\n TitleProps,\n SearchProps,\n LoadingProps,\n NoResultProps,\n ErrorProps,\n CancelButtonProps,\n LayoutProps,\n Padding,\n SnapPoint,\n AggregateReporter,\n};\nexport default SelectionViewer;\n","import React, { useCallback, useEffect, useRef, useState } from \"react\";\nimport { RowAggregateContext } from \"./SelectionViewer\";\nimport type { SelectionState } from \"./SelectionViewer\";\n\nexport type RowProps = {\n id?: string;\n /** Consumer-owned — SelectionViewer has never owned fetch/filter state, so unlike\n * search-viewer's Row this isn't internally computed. Mirrors how `selectionState`\n * is already a prop on SelectionViewer itself today. Defaults to \"data\": if you\n * render children without wiring this, we assume what you rendered IS the data. */\n state?: SelectionState;\n /** Called when this Row is scrolled horizontally near its end. Return (or resolve to)\n * `true` if more data may follow (keeps the pagination trigger armed), `false` once\n * there's nothing left to fetch — mirrors SelectionViewer's own `onPaginate` contract. */\n onPaginate?: () => boolean | Promise<boolean>;\n className?: string;\n style?: React.CSSProperties;\n children?: React.ReactNode;\n};\n\n/** A horizontally-scrolling, independently-paginating section — the Row/Column\n * equivalent for `SelectionViewer`. No shared code with `@academix-admin/search-viewer`'s\n * Row (Library Charter: packages stay mutually independent) — this one has no\n * query/debounce/cache engine of its own since `SelectionViewer` never had one either;\n * the consumer owns fetching/filtering and just tells this Row what `state` it's in. */\nfunction Row({ id: providedId, state = \"data\", onPaginate, className, style, children }: RowProps) {\n const aggregateReporter = React.useContext(RowAggregateContext);\n const [rowId] = useState(() => providedId || `row-${Math.random().toString(36).substring(2, 11)}`);\n const containerRef = useRef<HTMLDivElement | null>(null);\n const isPaginating = useRef(false);\n\n const handleScroll = useCallback(async () => {\n const el = containerRef.current;\n if (!el || isPaginating.current || !onPaginate) return;\n\n // Same \"near the end\" threshold as SelectionViewer's own vertical pagination trigger, adapted\n // to horizontal scroll metrics since a Row scrolls sideways.\n const { scrollLeft, scrollWidth, clientWidth } = el;\n if (scrollWidth - scrollLeft > clientWidth * 1.2) return;\n\n isPaginating.current = true;\n const hasMore = await onPaginate();\n if (!hasMore) {\n isPaginating.current = false;\n } else {\n setTimeout(() => {\n isPaginating.current = false;\n }, 500);\n }\n }, [onPaginate]);\n\n useEffect(() => {\n const el = containerRef.current;\n if (!el || !onPaginate) return;\n el.addEventListener(\"scroll\", handleScroll);\n return () => el.removeEventListener(\"scroll\", handleScroll);\n }, [handleScroll, onPaginate]);\n\n useEffect(() => {\n aggregateReporter?.report(rowId, state);\n return () => aggregateReporter?.unreport(rowId);\n }, [aggregateReporter, rowId, state]);\n\n return (\n <div\n ref={containerRef}\n className={className ? `selection-viewer-row ${className}` : \"selection-viewer-row\"}\n style={{\n display: \"flex\",\n flexDirection: \"row\",\n gap: \"8px\",\n overflowX: \"auto\",\n overflowY: \"hidden\",\n ...style,\n }}\n >\n {children}\n </div>\n );\n}\n\nRow.displayName = \"Row\";\n\nexport { Row };\n","import React, { useCallback, useEffect, useMemo, useState } from \"react\";\nimport { RowAggregateContext, SelectionViewerAggregateContext, computeAggregateState } from \"./SelectionViewer\";\nimport type { SelectionState } from \"./SelectionViewer\";\n\nexport type ColumnProps = {\n id?: string;\n className?: string;\n style?: React.CSSProperties;\n children?: React.ReactNode;\n};\n\n/** A vertical arrangement of `Row`s (or other content) — the explicit, composable\n * equivalent of today's flat `children` list. Its default layout is deliberately\n * identical to the existing `.selection-viewer-content.vertical` rendering\n * (`flex-direction: column, gap: 8px`), so today's flat usage is, unchanged, \"an\n * implicit Column with no Rows.\"\n *\n * Provides the `RowAggregateContext` its `Row` children report into, computes ONE\n * cumulative state from everything reported, and is itself a reporter one level up:\n * nested inside another `Column` it reports through that Column's `RowAggregateContext`\n * (behaving like a Row); at the top level it reports through `SelectionViewerAggregateContext`,\n * which `SelectionViewer` provides — this drives the outer sheet's loading/empty/error\n * views automatically with zero manual wiring, and lets Columns nest arbitrarily deep. */\nfunction Column({ id: providedId, className, style, children }: ColumnProps) {\n const [columnId] = useState(\n () => providedId || `column-${Math.random().toString(36).substring(2, 11)}`\n );\n\n const [reportedStates, setReportedStates] = useState<Map<string, SelectionState>>(new Map());\n const report = useCallback((id: string, state: SelectionState) => {\n setReportedStates((prev) => {\n const next = new Map(prev);\n next.set(id, state);\n return next;\n });\n }, []);\n const unreport = useCallback((id: string) => {\n setReportedStates((prev) => {\n if (!prev.has(id)) return prev;\n const next = new Map(prev);\n next.delete(id);\n return next;\n });\n }, []);\n const rowAggregateValue = useMemo(() => ({ report, unreport }), [report, unreport]);\n\n const aggregateState =\n reportedStates.size > 0 ? computeAggregateState(Array.from(reportedStates.values())) : \"initial\";\n\n const parentRowAggregate = React.useContext(RowAggregateContext);\n const selectionViewerAggregate = React.useContext(SelectionViewerAggregateContext);\n const upstreamReporter = parentRowAggregate ?? selectionViewerAggregate;\n\n useEffect(() => {\n if (!upstreamReporter) return;\n upstreamReporter.report(columnId, aggregateState);\n return () => upstreamReporter.unreport(columnId);\n }, [upstreamReporter, columnId, aggregateState]);\n\n return (\n <RowAggregateContext.Provider value={rowAggregateValue}>\n <div\n className={className ? `selection-viewer-column ${className}` : \"selection-viewer-column\"}\n style={{ display: \"flex\", flexDirection: \"column\", gap: \"8px\", ...style }}\n >\n {children}\n </div>\n </RowAggregateContext.Provider>\n );\n}\n\nColumn.displayName = \"Column\";\n\nexport { Column };\n"]}
1
+ {"version":3,"sources":["../src/SelectionViewer.tsx","../src/Row.tsx","../src/Column.tsx"],"names":["React","useState","useRef","useCallback","useEffect","jsx","useMemo"],"mappings":"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","file":"index.js","sourcesContent":["import React, { useState, useEffect, useCallback, useRef, useMemo } from \"react\";\r\nimport { Sheet } from \"@academix-admin/modal-sheet\";\r\n\r\n// ==================== Aggregation (Row/Column) ====================\r\n// Independent from @academix-admin/search-viewer's equivalent (Library Charter: packages stay\r\n// mutually independent) — same shape, duplicated intentionally rather than shared.\r\n\r\ntype AggregateReporter = {\r\n report: (id: string, state: SelectionState) => void;\r\n unreport: (id: string) => void;\r\n};\r\n\r\n/** A `Row` reports its own `state` into the nearest `Column` through this. */\r\nconst RowAggregateContext = React.createContext<AggregateReporter | null>(null);\r\n\r\n/** `Column` reports its own aggregated state up through this — `SelectionViewer` provides it and\r\n * merges whatever's reported into its own selectionState resolution, with zero extra wiring. */\r\nconst SelectionViewerAggregateContext = React.createContext<AggregateReporter | null>(null);\r\n\r\nfunction computeAggregateState(states: SelectionState[]): SelectionState {\r\n if (states.length === 0) return \"initial\";\r\n if (states.some((s) => s === \"data\")) return \"data\";\r\n if (states.some((s) => s === \"loading\")) return \"loading\";\r\n if (states.every((s) => s === \"empty\")) return \"empty\";\r\n if (states.some((s) => s === \"error\")) return \"error\";\r\n return \"initial\";\r\n}\r\n\r\n// ==================== Types ====================\r\ntype Padding = {\r\n l: string;\r\n r: string;\r\n t: string;\r\n b: string;\r\n};\r\n\r\ntype SnapPoint = number;\r\n\r\ntype SelectionState = \"loading\" | \"empty\" | \"error\" | \"data\" | \"initial\";\r\n\r\n\r\ntype TitleProps = {\r\n text: string;\r\n textColor: string;\r\n className?: string;\r\n containerClass?: string;\r\n style?: React.CSSProperties;\r\n};\r\n\r\ntype SearchProps = {\r\n text: string;\r\n textColor: string;\r\n className?: string;\r\n background?: string;\r\n prefixIcon?: React.ReactNode;\r\n suffixIcon?: React.ReactNode;\r\n clearIcon?: React.ReactNode;\r\n backIcon?: React.ReactNode;\r\n prefixGap?: string;\r\n suffixGap?: string;\r\n padding?: Padding;\r\n autoFocus?: boolean;\r\n inputStyle?: React.CSSProperties;\r\n containerStyle?: React.CSSProperties;\r\n onChange?: (value: string) => void;\r\n onFocus?: () => void;\r\n onBlur?: () => void;\r\n};\r\n\r\ntype LoadingProps = {\r\n view: React.ReactNode;\r\n padding?: Padding;\r\n style?: React.CSSProperties;\r\n};\r\n\r\ntype NoResultProps = {\r\n view: React.ReactNode;\r\n text?: string;\r\n padding?: Padding;\r\n style?: React.CSSProperties;\r\n};\r\n\r\ntype ErrorProps = {\r\n view: React.ReactNode;\r\n text?: string;\r\n padding?: Padding;\r\n style?: React.CSSProperties;\r\n};\r\n\r\ntype CancelButtonProps = {\r\n text?: string;\r\n view: React.ReactNode;\r\n position?: \"left\" | \"right\";\r\n style?: React.CSSProperties;\r\n onClick?: () => void;\r\n};\r\n\r\ntype LayoutProps = {\r\n gapBetweenHandleAndTitle?: string;\r\n gapBetweenTitleAndSearch?: string;\r\n gapBetweenSearchAndContent?: string;\r\n backgroundColor?: string;\r\n handleColor?: string;\r\n handleWidth?: string;\r\n fullScreenSearchBackground?: string;\r\n fullScreenSearchHeaderStyle?: React.CSSProperties;\r\n maxWidth?: string;\r\n};\r\n\r\ntype SelectionViewerProps = {\r\n id?: string;\r\n isOpen: boolean;\r\n backDrop?: boolean;\r\n onClose: () => void;\r\n titleProp: TitleProps;\r\n searchProp?: SearchProps;\r\n loadingProp?: LoadingProps;\r\n noResultProp?: NoResultProps;\r\n errorProp?: ErrorProps;\r\n cancelButton?: CancelButtonProps;\r\n layoutProp?: LayoutProps;\r\n childrenDirection?: \"vertical\" | \"horizontal\";\r\n children?: React.ReactNode;\r\n onPaginate?: () => boolean | Promise<boolean>;\r\n snapPoints?: SnapPoint[];\r\n initialSnap?: number;\r\n unmountOnClose?: boolean;\r\n zIndex?: number;\r\n /**\r\n * Accessible name for the sheet, announced when it opens.\r\n *\r\n * A modal with no name is announced simply as \"dialog\", which tells a screen-reader user that\r\n * something has taken over the screen and nothing at all about what.\r\n */\r\n ariaLabel?: string;\r\n maxHeight?: string;\r\n minHeight?: string;\r\n selectionState?: SelectionState;\r\n closeThreshold?: number;\r\n};\r\n\r\n// ==================== Styles ====================\r\nconst getStyles = (id: string) => `\r\n#${id} .selection-viewer-header {\r\n padding: 0px;\r\n display: flex;\r\n flex-direction: column;\r\n align-items: center;\r\n position: relative;\r\n width: 100%;\r\n}\r\n\r\n#${id} .selection-viewer-drag-handle {\r\n height: 5px;\r\n border-radius: 3px;\r\n margin-top: 16px;\r\n}\r\n\r\n#${id} .selection-viewer-container {\r\n display: flex;\r\n align-items: flex-start;\r\n width: 100%;\r\n}\r\n\r\n#${id} .selection-viewer-title {\r\n margin: 0px;\r\n font-size: 18px;\r\n font-weight: 600;\r\n padding: 0px 16px 0px 16px;\r\n word-break: break-word; /* break long words */\r\n white-space: normal; /* allow wrapping */\r\n}\r\n\r\n#${id} .selection-viewer-search {\r\n display: flex;\r\n align-items: center;\r\n margin: 16px 16px 4px 16px;\r\n border-radius: 12px;\r\n box-sizing: border-box;\r\n border: 1px solid rgba(0, 0, 0, 0.1);\r\n}\r\n\r\n#${id} .selection-viewer-search-input {\r\n flex: 1;\r\n border: none;\r\n background: transparent;\r\n padding: 12px 8px;\r\n outline: none;\r\n font-size: 16px !important;\r\n width: 100%;\r\n}\r\n\r\n#${id} .selection-viewer-content {\r\n overflow-y: auto;\r\n -webkit-overflow-scrolling: touch;\r\n flex: 1;\r\n min-height: 0;\r\n}\r\n\r\n#${id} .selection-viewer-content.vertical {\r\n display: flex;\r\n flex-direction: column;\r\n gap: 8px;\r\n}\r\n\r\n#${id} .selection-viewer-content.horizontal {\r\n display: flex;\r\n flex-direction: row;\r\n gap: 8px;\r\n overflow-x: auto;\r\n overflow-y: hidden;\r\n}\r\n\r\n#${id} .selection-viewer-no-results,\r\n#${id} .selection-viewer-error,\r\n#${id} .selection-viewer-loading {\r\n display: flex;\r\n justify-content: center;\r\n align-items: center;\r\n min-height: 120px;\r\n}\r\n\r\n#${id} .selection-viewer-default-no-results {\r\n color: #666;\r\n font-size: 14px;\r\n}\r\n\r\n#${id} .selection-viewer-default-error {\r\n color: red;\r\n font-size: 14px;\r\n}\r\n\r\n/* Full screen search mode */\r\n#${id} .selection-viewer-fullscreen-search {\r\n// position: fixed;\r\n top: 0;\r\n left: 0;\r\n right: 0;\r\n z-index: 10;\r\n// padding-top: env(safe-area-inset-top);\r\n width: 100%;\r\n}\r\n\r\n#${id} .selection-viewer-search-back-button {\r\n background: none;\r\n border: none;\r\n padding: 8px;\r\n margin-right: 4px;\r\n display: flex;\r\n align-items: center;\r\n justify-content: center;\r\n cursor: pointer;\r\n transition: opacity 0.2s;\r\n}\r\n\r\n#${id} .selection-viewer-search-back-button:hover {\r\n opacity: 0.7;\r\n}\r\n\r\n#${id} .selection-viewer-search-clear-button {\r\n background: none;\r\n border: none;\r\n padding: 8px;\r\n margin-left: 4px;\r\n display: flex;\r\n align-items: center;\r\n justify-content: center;\r\n cursor: pointer;\r\n transition: opacity 0.2s;\r\n}\r\n\r\n#${id} .selection-viewer-search-clear-button:hover {\r\n opacity: 0.7;\r\n}\r\n\r\n/* React Modal Sheet overrides */\r\n#${id} .react-modal-sheet-container {\r\n max-width: 500px;\r\n margin: 0 auto;\r\n border-top-left-radius: 16px;\r\n border-top-right-radius: 16px;\r\n}\r\n\r\n#${id} .react-modal-sheet-backdrop {\r\n background-color: rgba(0, 0, 0, 0.5) !important;\r\n pointer-events: auto !important;\r\n}\r\n\r\n#${id} .react-modal-sheet-content {\r\n padding: 0 0px 0px 0px;\r\n height: 100%;\r\n}\r\n\r\n\r\n/* Mobile full-width behavior */\r\n@media (max-width: 500px) {\r\n #${id} .react-modal-sheet-container {\r\n max-width: 100%;\r\n border-radius: 0;\r\n }\r\n}\r\n\r\n/* Prevent iOS zooming */\r\n@media screen and (-webkit-min-device-pixel-ratio: 0) {\r\n #${id} .selection-viewer-search-input {\r\n font-size: 16px !important;\r\n }\r\n}\r\n`;\r\n\r\n// ==================== Hook to inject CSS per instance ====================\r\nconst useInjectStyles = (id: string) => {\r\n useEffect(() => {\r\n const styleId = `selection-viewer-styles-${id}`;\r\n let styleTag = document.getElementById(styleId) as HTMLStyleElement | null;\r\n\r\n if (!styleTag) {\r\n styleTag = document.createElement(\"style\");\r\n styleTag.id = styleId;\r\n styleTag.innerHTML = getStyles(id);\r\n document.head.appendChild(styleTag);\r\n }\r\n\r\n // Cleanup on unmount\r\n return () => {\r\n if (styleTag && document.head.contains(styleTag)) {\r\n document.head.removeChild(styleTag);\r\n }\r\n };\r\n }, [id]);\r\n};\r\n\r\n// ==================== Component ====================\r\n/**\r\n * Escape closes the viewer, and Tab stays inside it.\r\n *\r\n * The viewer covers the screen, so what is behind it is not available — but nothing said so to the\r\n * keyboard. Tab walked out of the option list into the page underneath, where a person was\r\n * operating controls they could not see, and Escape did nothing at all, which is the one key\r\n * everybody reaches for to get out of a picker.\r\n *\r\n * Deliberately a private copy rather than an import from a sibling package: every library here\r\n * stands alone, and a shared helper between two of them is a dependency the consumer did not ask\r\n * for. Takes the container's `id` rather than a ref, because the sheet element belongs to the\r\n * underlying modal-sheet component; looking it up when a key is pressed finds it however that\r\n * component chooses to mount it. Focusables are re-queried on every Tab, since the option list\r\n * changes as the consumer filters it and a list captured on open is a list of dead elements.\r\n */\r\nconst useModalKeys = (isOpen: boolean, onClose: () => void, containerId: string) => {\r\n useEffect(() => {\r\n if (!isOpen || typeof document === \"undefined\") return;\r\n\r\n const onKeyDown = (e: KeyboardEvent) => {\r\n if (e.key === \"Escape\") {\r\n e.preventDefault();\r\n onClose();\r\n return;\r\n }\r\n if (e.key !== \"Tab\") return;\r\n\r\n const focusable = document.getElementById(containerId)?.querySelectorAll<HTMLElement>(\r\n 'a[href], button:not([disabled]), input:not([disabled]), select:not([disabled]),' +\r\n ' textarea:not([disabled]), [tabindex]:not([tabindex=\"-1\"])',\r\n );\r\n if (!focusable || focusable.length === 0) return;\r\n\r\n const first = focusable[0];\r\n const last = focusable[focusable.length - 1];\r\n\r\n if (e.shiftKey && document.activeElement === first) {\r\n e.preventDefault();\r\n last.focus();\r\n } else if (!e.shiftKey && document.activeElement === last) {\r\n e.preventDefault();\r\n first.focus();\r\n }\r\n };\r\n\r\n document.addEventListener(\"keydown\", onKeyDown);\r\n return () => document.removeEventListener(\"keydown\", onKeyDown);\r\n }, [isOpen, onClose, containerId]);\r\n};\r\n\r\nconst SelectionViewer: React.FC<SelectionViewerProps> = ({\r\n id: providedId,\r\n isOpen,\r\n backDrop = true,\r\n onClose,\r\n titleProp,\r\n searchProp,\r\n loadingProp,\r\n noResultProp,\r\n errorProp,\r\n cancelButton,\r\n layoutProp,\r\n childrenDirection = \"vertical\",\r\n children,\r\n onPaginate,\r\n snapPoints = [0, 1],\r\n initialSnap = 1,\r\n unmountOnClose = true,\r\n zIndex = 1000,\r\n ariaLabel,\r\n maxHeight = \"90dvh\",\r\n minHeight = \"65dvh\",\r\n selectionState: selectionStateProp = \"initial\",\r\n closeThreshold = 0.2,\r\n}) => {\r\n const [id] = useState(() => providedId || `selection-${Math.random().toString(36).substring(2, 11)}`);\r\n const [searchValue, setSearchValue] = useState(\"\");\r\n const [isSearchFocused, setIsSearchFocused] = useState(false);\r\n const [keyboardHeight, setKeyboardHeight] = useState(0);\r\n const [inputKey, setInputKey] = useState(0);\r\n const [shouldAutoFocus, setShouldAutoFocus] = useState(false);\r\n const isPaginating = useRef(false);\r\n const searchInputRef = useRef<HTMLInputElement>(null);\r\n const sheetRef = useRef<any>(null);\r\n const headerRef = useRef<HTMLDivElement>(null);\r\n\r\n useInjectStyles(id);\r\n // Escape closes the viewer and Tab stays inside it — see useModalKeys.\r\n useModalKeys(isOpen, onClose, id);\r\n\r\n // Descendant sections (a Column, or anything else) can report a cumulative state up through this —\r\n // starts empty, so a plain SelectionViewer with no Row/Column children behaves exactly as before.\r\n const [reportedStates, setReportedStates] = useState<Map<string, SelectionState>>(new Map());\r\n const reportAggregate = useCallback((reporterId: string, state: SelectionState) => {\r\n setReportedStates((prev) => {\r\n const next = new Map(prev);\r\n next.set(reporterId, state);\r\n return next;\r\n });\r\n }, []);\r\n const unreportAggregate = useCallback((reporterId: string) => {\r\n setReportedStates((prev) => {\r\n if (!prev.has(reporterId)) return prev;\r\n const next = new Map(prev);\r\n next.delete(reporterId);\r\n return next;\r\n });\r\n }, []);\r\n const aggregateReporterValue = useMemo(\r\n () => ({ report: reportAggregate, unreport: unreportAggregate }),\r\n [reportAggregate, unreportAggregate]\r\n );\r\n const reportedAggregate =\r\n reportedStates.size > 0 ? computeAggregateState(Array.from(reportedStates.values())) : null;\r\n const isComposed = reportedAggregate !== null;\r\n\r\n // Precedence: an explicit `selectionState` prop always wins (matches today's exact behaviour for\r\n // any consumer not using Row/Column) -> then a reported Column aggregate, if one exists -> \"initial\".\r\n const selectionState =\r\n selectionStateProp !== \"initial\" ? selectionStateProp : reportedAggregate ?? \"initial\";\r\n\r\n // Track keyboard height\r\n useEffect(() => {\r\n if (typeof window === 'undefined' || !window.visualViewport) return;\r\n\r\n const handleResize = () => {\r\n const vp = window.visualViewport!;\r\n const kbHeight = window.innerHeight - vp.height;\r\n setKeyboardHeight(kbHeight > 0 ? kbHeight : 0);\r\n };\r\n\r\n window.visualViewport.addEventListener('resize', handleResize);\r\n window.visualViewport.addEventListener('scroll', handleResize);\r\n\r\n return () => {\r\n window.visualViewport?.removeEventListener('resize', handleResize);\r\n window.visualViewport?.removeEventListener('scroll', handleResize);\r\n };\r\n }, []);\r\n\r\n // Auto-focus on search\r\n useEffect(() => {\r\n if (!isOpen) {\r\n searchInputRef.current?.blur();\r\n setSearchValue(\"\");\r\n searchProp?.onChange?.(\"\");\r\n setShouldAutoFocus(false);\r\n return;\r\n }\r\n }, [isOpen, searchProp?.autoFocus]);\r\n\r\n const handleOpenEnd = useCallback(() => {\r\n if (searchProp?.autoFocus && searchInputRef.current) {\r\n setInputKey(prev => prev + 1);\r\n setShouldAutoFocus(true);\r\n searchInputRef.current.focus();\r\n searchInputRef.current.click();\r\n }\r\n }, [searchProp?.autoFocus]);\r\n\r\n const handleSearchChange = (e: React.ChangeEvent<HTMLInputElement>) => {\r\n const value = e.target.value;\r\n setSearchValue(value);\r\n searchProp?.onChange?.(value);\r\n };\r\n\r\n const handleSearchFocus = () => {\r\n setIsSearchFocused(true);\r\n searchProp?.onFocus?.();\r\n requestAnimationFrame(() => {\r\n searchInputRef.current?.focus();\r\n });\r\n };\r\n\r\n const handleSearchBlur = () => {\r\n searchProp?.onBlur?.();\r\n };\r\n\r\n const handleBackFromSearch = () => {\r\n setIsSearchFocused(false);\r\n if (searchInputRef.current) {\r\n searchInputRef.current.blur();\r\n }\r\n };\r\n\r\n const clearSearch = () => {\r\n setSearchValue(\"\");\r\n searchProp?.onChange?.(\"\");\r\n if (searchInputRef.current) {\r\n searchInputRef.current.focus();\r\n }\r\n };\r\n\r\n const handleScroll = useCallback(\r\n async (e: React.UIEvent<HTMLDivElement>) => {\r\n if (isPaginating.current || !onPaginate) return;\r\n\r\n const { scrollTop, scrollHeight, clientHeight } = e.currentTarget;\r\n const isNearBottom = scrollHeight - scrollTop <= clientHeight * 1.2;\r\n\r\n if (isNearBottom) {\r\n isPaginating.current = true;\r\n const hasMore = await onPaginate();\r\n if (!hasMore) {\r\n isPaginating.current = false;\r\n } else {\r\n setTimeout(() => {\r\n isPaginating.current = false;\r\n }, 500);\r\n }\r\n }\r\n },\r\n [onPaginate]\r\n );\r\n\r\n if (!isOpen && unmountOnClose) return null;\r\n\r\n return (\r\n <SelectionViewerAggregateContext.Provider value={aggregateReporterValue}>\r\n <Sheet\r\n ref={sheetRef}\r\n isOpen={isOpen}\r\n onClose={onClose}\r\n detent=\"content\"\r\n style={{ zIndex }}\r\n maxHeight={maxHeight}\r\n onOpenEnd={handleOpenEnd}\r\n >\r\n <Sheet.Container\r\n id={id}\r\n // Announced as a modal dialog. Without this a screen reader reads the sheet as one more\r\n // region of the page and gives no indication that what is behind it is unavailable — and\r\n // an automated check for an open dialog finds nothing at all.\r\n role=\"dialog\"\r\n aria-modal=\"true\"\r\n aria-label={ariaLabel}\r\n style={{\r\n maxHeight: maxHeight,\r\n minHeight: isSearchFocused ? \"100dvh\" : minHeight,\r\n maxWidth: layoutProp?.maxWidth ?? '800px',\r\n margin: \"0 auto\",\r\n width: \"100%\",\r\n left: 0,\r\n right: 0,\r\n paddingBottom: \"calc(0px + env(safe-area-inset-bottom))\",\r\n background: isSearchFocused\r\n ? layoutProp?.fullScreenSearchBackground || layoutProp?.backgroundColor\r\n : layoutProp?.backgroundColor,\r\n borderTopLeftRadius: isSearchFocused ? \"0px\" : \"16px\",\r\n borderTopRightRadius: isSearchFocused ? \"0px\" : \"16px\",\r\n }}\r\n >\r\n {isSearchFocused ? (\r\n <Sheet.Header>\r\n <div\r\n className=\"selection-viewer-fullscreen-search\"\r\n style={layoutProp?.fullScreenSearchHeaderStyle}\r\n >\r\n <div className=\"selection-viewer-search\" style={{\r\n ...searchProp?.containerStyle,\r\n background: searchProp?.background,\r\n padding: searchProp?.padding\r\n ? `${searchProp.padding.t} ${searchProp.padding.r} ${searchProp.padding.b} ${searchProp.padding.l}`\r\n : \"16px\"\r\n }}>\r\n <button\r\n className=\"selection-viewer-search-back-button\"\r\n onClick={handleBackFromSearch}\r\n aria-label=\"Exit search mode\"\r\n >\r\n {searchProp?.backIcon || (\r\n <svg width=\"24\" height=\"24\" viewBox=\"0 0 24 24\" fill=\"none\" xmlns=\"http://www.w3.org/2000/svg\">\r\n <path d=\"M15 18L9 12L15 6\" stroke={searchProp?.textColor || 'currentColor'} strokeWidth=\"2\" strokeLinecap=\"round\" strokeLinejoin=\"round\" />\r\n </svg>\r\n )}\r\n </button>\r\n\r\n <input\r\n key={inputKey}\r\n ref={searchInputRef}\r\n type=\"text\"\r\n placeholder={searchProp?.text}\r\n value={searchValue}\r\n onChange={handleSearchChange}\r\n className={searchProp?.className || \"selection-viewer-search-input\"}\r\n style={{\r\n color: searchProp?.textColor,\r\n ...searchProp?.inputStyle\r\n }}\r\n onFocus={handleSearchFocus}\r\n onBlur={handleSearchBlur}\r\n autoFocus={shouldAutoFocus}\r\n />\r\n\r\n {searchValue && (\r\n <button\r\n className=\"selection-viewer-search-clear-button\"\r\n onClick={clearSearch}\r\n aria-label=\"Clear search\"\r\n >\r\n {searchProp?.clearIcon || (\r\n <svg width=\"24\" height=\"24\" viewBox=\"0 0 24 24\" fill=\"none\" xmlns=\"http://www.w3.org/2000/svg\">\r\n <path d=\"M18 6L6 18M6 6L18 18\" stroke={searchProp?.textColor || 'currentColor'} strokeWidth=\"2\" strokeLinecap=\"round\" strokeLinejoin=\"round\" />\r\n </svg>\r\n )}\r\n </button>\r\n )}\r\n </div>\r\n </div>\r\n </Sheet.Header>\r\n ) : (\r\n <Sheet.Header>\r\n <div className=\"selection-viewer-header\">\r\n {/* Cancel button left */}\r\n {cancelButton?.position === \"left\" && (\r\n <button\r\n style={{\r\n position: \"absolute\",\r\n left: \"0px\",\r\n top: \"8px\",\r\n border: \"none\",\r\n backgroundColor: \"transparent\",\r\n ...cancelButton.style\r\n }}\r\n onClick={cancelButton.onClick || onClose}\r\n >\r\n {cancelButton.view || cancelButton.text || \"Cancel\"}\r\n </button>\r\n )}\r\n\r\n {/* Drag handle */}\r\n {!isSearchFocused && (\r\n <div\r\n className=\"selection-viewer-drag-handle\"\r\n style={{\r\n background: layoutProp?.handleColor || \"#ccc\",\r\n width: layoutProp?.handleWidth || \"40px\",\r\n marginBottom: layoutProp?.gapBetweenHandleAndTitle || \"12px\",\r\n }}\r\n />\r\n )}\r\n\r\n {/* Cancel button right */}\r\n {cancelButton?.position === \"right\" && (\r\n <button\r\n style={{\r\n position: \"absolute\",\r\n right: \"0px\",\r\n top: \"8px\",\r\n border: \"none\",\r\n backgroundColor: \"transparent\",\r\n ...cancelButton.style\r\n }}\r\n onClick={cancelButton.onClick || onClose}\r\n >\r\n {cancelButton.view || cancelButton.text || \"Cancel\"}\r\n </button>\r\n )}\r\n\r\n {/* Title */}\r\n <div className={titleProp.containerClass || \"selection-viewer-container\"}>\r\n <h2\r\n id={`${id}-title`}\r\n className={titleProp.className || \"selection-viewer-title\"}\r\n style={{\r\n marginBottom: layoutProp?.gapBetweenTitleAndSearch || \"8px\",\r\n color: titleProp?.textColor || 'black',\r\n ...titleProp.style\r\n }}\r\n >\r\n {titleProp.text}\r\n </h2>\r\n </div>\r\n </div>\r\n\r\n {/* Search */}\r\n {searchProp && (\r\n <div\r\n className=\"selection-viewer-search\"\r\n style={{\r\n background: searchProp.background,\r\n padding: searchProp.padding\r\n ? `${searchProp.padding.t} ${searchProp.padding.r} ${searchProp.padding.b} ${searchProp.padding.l}`\r\n : \"8px 16px\",\r\n marginBottom: layoutProp?.gapBetweenSearchAndContent,\r\n ...searchProp.containerStyle\r\n }}\r\n >\r\n {searchProp.prefixIcon && (\r\n <span style={{ marginRight: searchProp.prefixGap || \"8px\" }}>\r\n {searchProp.prefixIcon}\r\n </span>\r\n )}\r\n <input\r\n key={inputKey}\r\n ref={searchInputRef}\r\n type=\"text\"\r\n placeholder={searchProp.text}\r\n value={searchValue}\r\n onChange={handleSearchChange}\r\n className={searchProp.className || \"selection-viewer-search-input\"}\r\n style={{\r\n color: searchProp?.textColor,\r\n ...searchProp.inputStyle\r\n }}\r\n onFocus={handleSearchFocus}\r\n onBlur={handleSearchBlur}\r\n autoFocus={shouldAutoFocus}\r\n />\r\n {searchValue && (\r\n <button\r\n className=\"selection-viewer-search-clear-button\"\r\n onClick={clearSearch}\r\n aria-label=\"Clear search\"\r\n style={{ marginLeft: searchProp.suffixGap || \"8px\" }}\r\n >\r\n {searchProp.clearIcon || searchProp.suffixIcon || (\r\n <svg width=\"24\" height=\"24\" viewBox=\"0 0 24 24\" fill=\"none\" xmlns=\"http://www.w3.org/2000/svg\">\r\n <path d=\"M18 6L6 18M6 6L18 18\" stroke=\"currentColor\" strokeWidth=\"2\" strokeLinecap=\"round\" strokeLinejoin=\"round\" />\r\n </svg>\r\n )}\r\n </button>\r\n )}\r\n {!searchValue && searchProp.suffixIcon && (\r\n <span style={{ marginLeft: searchProp.suffixGap || \"8px\" }}>\r\n {searchProp.suffixIcon}\r\n </span>\r\n )}\r\n </div>\r\n )}\r\n </Sheet.Header>\r\n )}\r\n\r\n <Sheet.Content>\r\n <div\r\n className={`selection-viewer-content ${childrenDirection}`}\r\n onScroll={onPaginate ? handleScroll : undefined}\r\n style={{\r\n paddingTop: isSearchFocused ? layoutProp?.gapBetweenSearchAndContent : '0',\r\n paddingBottom: keyboardHeight > 0\r\n ? `${keyboardHeight + 16}px`\r\n : '16px',\r\n }}\r\n >\r\n {/* Show children first, then loading at bottom */}\r\n {React.Children.count(children) > 0 ? (\r\n <>\r\n {children}\r\n {selectionState === \"loading\" && (\r\n <div\r\n className=\"selection-viewer-loading\"\r\n style={{\r\n padding: loadingProp?.padding\r\n ? `${loadingProp.padding.t} ${loadingProp.padding.r} ${loadingProp.padding.b} ${loadingProp.padding.l}`\r\n : \"16px\",\r\n ...loadingProp?.style\r\n }}\r\n >\r\n {loadingProp?.view}\r\n </div>\r\n )}\r\n {/* Composed mode: a Column/Row descendant reports its own state, which can only ever be\r\n \"empty\"/\"error\" here since the child count > 0 branch is unconditional on a literal\r\n <Column> being present. Layer the outer view alongside the (visually empty) children\r\n rather than replacing them — a Column/Row must stay mounted to keep reporting. */}\r\n {isComposed && selectionState === \"empty\" && (\r\n <div\r\n className=\"selection-viewer-no-results\"\r\n style={{\r\n padding: noResultProp?.padding\r\n ? `${noResultProp.padding.t} ${noResultProp.padding.r} ${noResultProp.padding.b} ${noResultProp.padding.l}`\r\n : \"16px\",\r\n ...noResultProp?.style\r\n }}\r\n >\r\n {noResultProp?.view || (\r\n <div className=\"selection-viewer-default-no-results\">\r\n {noResultProp?.text || \"No results found\"}\r\n </div>\r\n )}\r\n </div>\r\n )}\r\n {isComposed && selectionState === \"error\" && (\r\n <div\r\n className=\"selection-viewer-error\"\r\n style={{\r\n padding: errorProp?.padding\r\n ? `${errorProp.padding.t} ${errorProp.padding.r} ${errorProp.padding.b} ${errorProp.padding.l}`\r\n : \"16px\",\r\n ...errorProp?.style\r\n }}\r\n >\r\n {errorProp?.view || (\r\n <div className=\"selection-viewer-default-error\">\r\n {errorProp?.text || \"No results found\"}\r\n </div>\r\n )}\r\n </div>\r\n )}\r\n </>\r\n ) : (selectionState === \"empty\" || (React.Children.count(children) <= 0 && (selectionState != \"loading\" && selectionState != \"error\"))) ? (\r\n <div\r\n className=\"selection-viewer-no-results\"\r\n style={{\r\n padding: noResultProp?.padding\r\n ? `${noResultProp.padding.t} ${noResultProp.padding.r} ${noResultProp.padding.b} ${noResultProp.padding.l}`\r\n : \"16px\",\r\n ...noResultProp?.style\r\n }}\r\n >\r\n {noResultProp?.view || (\r\n <div className=\"selection-viewer-default-no-results\">\r\n {noResultProp?.text || \"No results found\"}\r\n </div>\r\n )}\r\n </div>\r\n ) : selectionState === \"loading\" ? (\r\n <div\r\n className=\"selection-viewer-loading\"\r\n style={{\r\n padding: loadingProp?.padding\r\n ? `${loadingProp.padding.t} ${loadingProp.padding.r} ${loadingProp.padding.b} ${loadingProp.padding.l}`\r\n : \"16px\",\r\n ...loadingProp?.style\r\n }}\r\n >\r\n {loadingProp?.view}\r\n </div>\r\n ) : (selectionState === \"error\") ? (\r\n <div\r\n className=\"selection-viewer-error\"\r\n style={{\r\n padding: errorProp?.padding\r\n ? `${errorProp.padding.t} ${errorProp.padding.r} ${errorProp.padding.b} ${errorProp.padding.l}`\r\n : \"16px\",\r\n ...errorProp?.style\r\n }}\r\n >\r\n {errorProp?.view || (\r\n <div className=\"selection-viewer-default-error\">\r\n {errorProp?.text || \"No results found\"}\r\n </div>\r\n )}\r\n </div>\r\n ) : null}\r\n </div>\r\n </Sheet.Content>\r\n </Sheet.Container>\r\n <Sheet.Backdrop onTap={backDrop ? onClose : undefined} />\r\n </Sheet>\r\n </SelectionViewerAggregateContext.Provider>\r\n );\r\n};\r\n\r\n// ==================== Controller Hook ====================\r\ntype Operation = {\r\n open: () => void;\r\n close: () => void;\r\n toggle: () => void;\r\n setSelectionState: (val: SelectionState) => void;\r\n};\r\n\r\nconst useSelectionController = (initialSelectionState?: SelectionState): [\r\n string,\r\n Operation,\r\n boolean,\r\n SelectionState\r\n] => {\r\n const [isOpen, setIsOpen] = useState(false);\r\n const [selectionState, setSelectionState] = useState(initialSelectionState || 'initial');\r\n const [selectionId] = useState(() => `selection-${Math.random().toString(36).substring(2, 11)}`);\r\n\r\n const operations = useMemo<Operation>(() => ({\r\n open: () => setIsOpen(true),\r\n close: () => setIsOpen(false),\r\n toggle: () => setIsOpen((prev) => !prev),\r\n setSelectionState\r\n }), [setSelectionState]);\r\n\r\n return [selectionId, operations, isOpen, selectionState];\r\n};\r\n\r\nexport { SelectionViewer, useSelectionController, RowAggregateContext, SelectionViewerAggregateContext, computeAggregateState };\r\nexport type {\r\n SelectionViewerProps,\r\n SelectionState,\r\n TitleProps,\r\n SearchProps,\r\n LoadingProps,\r\n NoResultProps,\r\n ErrorProps,\r\n CancelButtonProps,\r\n LayoutProps,\r\n Padding,\r\n SnapPoint,\r\n AggregateReporter,\r\n};\r\nexport default SelectionViewer;\r\n","import React, { useCallback, useEffect, useRef, useState } from \"react\";\nimport { RowAggregateContext } from \"./SelectionViewer\";\nimport type { SelectionState } from \"./SelectionViewer\";\n\nexport type RowProps = {\n id?: string;\n /** Consumer-owned — SelectionViewer has never owned fetch/filter state, so unlike\n * search-viewer's Row this isn't internally computed. Mirrors how `selectionState`\n * is already a prop on SelectionViewer itself today. Defaults to \"data\": if you\n * render children without wiring this, we assume what you rendered IS the data. */\n state?: SelectionState;\n /** Called when this Row is scrolled horizontally near its end. Return (or resolve to)\n * `true` if more data may follow (keeps the pagination trigger armed), `false` once\n * there's nothing left to fetch — mirrors SelectionViewer's own `onPaginate` contract. */\n onPaginate?: () => boolean | Promise<boolean>;\n className?: string;\n style?: React.CSSProperties;\n children?: React.ReactNode;\n};\n\n/** A horizontally-scrolling, independently-paginating section — the Row/Column\n * equivalent for `SelectionViewer`. No shared code with `@academix-admin/search-viewer`'s\n * Row (Library Charter: packages stay mutually independent) — this one has no\n * query/debounce/cache engine of its own since `SelectionViewer` never had one either;\n * the consumer owns fetching/filtering and just tells this Row what `state` it's in. */\nfunction Row({ id: providedId, state = \"data\", onPaginate, className, style, children }: RowProps) {\n const aggregateReporter = React.useContext(RowAggregateContext);\n const [rowId] = useState(() => providedId || `row-${Math.random().toString(36).substring(2, 11)}`);\n const containerRef = useRef<HTMLDivElement | null>(null);\n const isPaginating = useRef(false);\n\n const handleScroll = useCallback(async () => {\n const el = containerRef.current;\n if (!el || isPaginating.current || !onPaginate) return;\n\n // Same \"near the end\" threshold as SelectionViewer's own vertical pagination trigger, adapted\n // to horizontal scroll metrics since a Row scrolls sideways.\n const { scrollLeft, scrollWidth, clientWidth } = el;\n if (scrollWidth - scrollLeft > clientWidth * 1.2) return;\n\n isPaginating.current = true;\n const hasMore = await onPaginate();\n if (!hasMore) {\n isPaginating.current = false;\n } else {\n setTimeout(() => {\n isPaginating.current = false;\n }, 500);\n }\n }, [onPaginate]);\n\n useEffect(() => {\n const el = containerRef.current;\n if (!el || !onPaginate) return;\n el.addEventListener(\"scroll\", handleScroll);\n return () => el.removeEventListener(\"scroll\", handleScroll);\n }, [handleScroll, onPaginate]);\n\n useEffect(() => {\n aggregateReporter?.report(rowId, state);\n return () => aggregateReporter?.unreport(rowId);\n }, [aggregateReporter, rowId, state]);\n\n return (\n <div\n ref={containerRef}\n className={className ? `selection-viewer-row ${className}` : \"selection-viewer-row\"}\n style={{\n display: \"flex\",\n flexDirection: \"row\",\n gap: \"8px\",\n overflowX: \"auto\",\n overflowY: \"hidden\",\n ...style,\n }}\n >\n {children}\n </div>\n );\n}\n\nRow.displayName = \"Row\";\n\nexport { Row };\n","import React, { useCallback, useEffect, useMemo, useState } from \"react\";\nimport { RowAggregateContext, SelectionViewerAggregateContext, computeAggregateState } from \"./SelectionViewer\";\nimport type { SelectionState } from \"./SelectionViewer\";\n\nexport type ColumnProps = {\n id?: string;\n className?: string;\n style?: React.CSSProperties;\n children?: React.ReactNode;\n};\n\n/** A vertical arrangement of `Row`s (or other content) — the explicit, composable\n * equivalent of today's flat `children` list. Its default layout is deliberately\n * identical to the existing `.selection-viewer-content.vertical` rendering\n * (`flex-direction: column, gap: 8px`), so today's flat usage is, unchanged, \"an\n * implicit Column with no Rows.\"\n *\n * Provides the `RowAggregateContext` its `Row` children report into, computes ONE\n * cumulative state from everything reported, and is itself a reporter one level up:\n * nested inside another `Column` it reports through that Column's `RowAggregateContext`\n * (behaving like a Row); at the top level it reports through `SelectionViewerAggregateContext`,\n * which `SelectionViewer` provides — this drives the outer sheet's loading/empty/error\n * views automatically with zero manual wiring, and lets Columns nest arbitrarily deep. */\nfunction Column({ id: providedId, className, style, children }: ColumnProps) {\n const [columnId] = useState(\n () => providedId || `column-${Math.random().toString(36).substring(2, 11)}`\n );\n\n const [reportedStates, setReportedStates] = useState<Map<string, SelectionState>>(new Map());\n const report = useCallback((id: string, state: SelectionState) => {\n setReportedStates((prev) => {\n const next = new Map(prev);\n next.set(id, state);\n return next;\n });\n }, []);\n const unreport = useCallback((id: string) => {\n setReportedStates((prev) => {\n if (!prev.has(id)) return prev;\n const next = new Map(prev);\n next.delete(id);\n return next;\n });\n }, []);\n const rowAggregateValue = useMemo(() => ({ report, unreport }), [report, unreport]);\n\n const aggregateState =\n reportedStates.size > 0 ? computeAggregateState(Array.from(reportedStates.values())) : \"initial\";\n\n const parentRowAggregate = React.useContext(RowAggregateContext);\n const selectionViewerAggregate = React.useContext(SelectionViewerAggregateContext);\n const upstreamReporter = parentRowAggregate ?? selectionViewerAggregate;\n\n useEffect(() => {\n if (!upstreamReporter) return;\n upstreamReporter.report(columnId, aggregateState);\n return () => upstreamReporter.unreport(columnId);\n }, [upstreamReporter, columnId, aggregateState]);\n\n return (\n <RowAggregateContext.Provider value={rowAggregateValue}>\n <div\n className={className ? `selection-viewer-column ${className}` : \"selection-viewer-column\"}\n style={{ display: \"flex\", flexDirection: \"column\", gap: \"8px\", ...style }}\n >\n {children}\n </div>\n </RowAggregateContext.Provider>\n );\n}\n\nColumn.displayName = \"Column\";\n\nexport { Column };\n"]}
package/package.json CHANGED
@@ -1,76 +1,76 @@
1
- {
2
- "name": "@academix-admin/selection-viewer",
3
- "version": "0.2.0",
4
- "description": "Imperative React selection sheet — search + pick from a list — with a controller hook, built on @academix-admin/modal-sheet.",
5
- "keywords": [
6
- "react",
7
- "selection",
8
- "picker",
9
- "sheet",
10
- "modal",
11
- "search",
12
- "imperative",
13
- "controller"
14
- ],
15
- "license": "MIT",
16
- "author": "Academix",
17
- "repository": {
18
- "type": "git",
19
- "url": "git+https://github.com/academix-admin/academix-ui.git",
20
- "directory": "packages/selection-viewer"
21
- },
22
- "homepage": "https://github.com/academix-admin/academix-ui/tree/main/packages/selection-viewer#readme",
23
- "bugs": {
24
- "url": "https://github.com/academix-admin/academix-ui/issues"
25
- },
26
- "type": "module",
27
- "sideEffects": false,
28
- "files": [
29
- "dist",
30
- "README.md",
31
- "LICENSE"
32
- ],
33
- "main": "./dist/index.cjs",
34
- "module": "./dist/index.js",
35
- "types": "./dist/index.d.ts",
36
- "exports": {
37
- ".": {
38
- "import": {
39
- "types": "./dist/index.d.ts",
40
- "default": "./dist/index.js"
41
- },
42
- "require": {
43
- "types": "./dist/index.d.cts",
44
- "default": "./dist/index.cjs"
45
- }
46
- },
47
- "./package.json": "./package.json"
48
- },
49
- "scripts": {
50
- "build": "tsup",
51
- "clean": "rimraf dist",
52
- "dev": "tsup --watch",
53
- "test": "vitest run",
54
- "test:watch": "vitest",
55
- "typecheck": "tsc --noEmit"
56
- },
57
- "dependencies": {
58
- "@academix-admin/modal-sheet": "^0.1.0"
59
- },
60
- "peerDependencies": {
61
- "react": ">=18.0.0",
62
- "react-dom": ">=18.0.0"
63
- },
64
- "devDependencies": {
65
- "@types/react": "^19.0.0",
66
- "@types/react-dom": "^19.0.0",
67
- "react": "^18.3.1",
68
- "react-dom": "^18.3.1",
69
- "rimraf": "^6.0.1",
70
- "tsup": "^8.3.5",
71
- "typescript": "^5.9.3"
72
- },
73
- "publishConfig": {
74
- "access": "public"
75
- }
76
- }
1
+ {
2
+ "name": "@academix-admin/selection-viewer",
3
+ "version": "0.2.1",
4
+ "description": "Imperative React selection sheet \u2014 search + pick from a list \u2014 with a controller hook, built on @academix-admin/modal-sheet.",
5
+ "keywords": [
6
+ "react",
7
+ "selection",
8
+ "picker",
9
+ "sheet",
10
+ "modal",
11
+ "search",
12
+ "imperative",
13
+ "controller"
14
+ ],
15
+ "license": "MIT",
16
+ "author": "Academix",
17
+ "repository": {
18
+ "type": "git",
19
+ "url": "git+https://github.com/academix-admin/academix-ui.git",
20
+ "directory": "packages/selection-viewer"
21
+ },
22
+ "homepage": "https://github.com/academix-admin/academix-ui/tree/main/packages/selection-viewer#readme",
23
+ "bugs": {
24
+ "url": "https://github.com/academix-admin/academix-ui/issues"
25
+ },
26
+ "type": "module",
27
+ "sideEffects": false,
28
+ "files": [
29
+ "dist",
30
+ "README.md",
31
+ "LICENSE"
32
+ ],
33
+ "main": "./dist/index.cjs",
34
+ "module": "./dist/index.js",
35
+ "types": "./dist/index.d.ts",
36
+ "exports": {
37
+ ".": {
38
+ "import": {
39
+ "types": "./dist/index.d.ts",
40
+ "default": "./dist/index.js"
41
+ },
42
+ "require": {
43
+ "types": "./dist/index.d.cts",
44
+ "default": "./dist/index.cjs"
45
+ }
46
+ },
47
+ "./package.json": "./package.json"
48
+ },
49
+ "scripts": {
50
+ "build": "tsup",
51
+ "clean": "rimraf dist",
52
+ "dev": "tsup --watch",
53
+ "test": "vitest run",
54
+ "test:watch": "vitest",
55
+ "typecheck": "tsc --noEmit"
56
+ },
57
+ "dependencies": {
58
+ "@academix-admin/modal-sheet": "^0.1.0"
59
+ },
60
+ "peerDependencies": {
61
+ "react": ">=18.0.0",
62
+ "react-dom": ">=18.0.0"
63
+ },
64
+ "devDependencies": {
65
+ "@types/react": "^19.0.0",
66
+ "@types/react-dom": "^19.0.0",
67
+ "react": "^18.3.1",
68
+ "react-dom": "^18.3.1",
69
+ "rimraf": "^6.0.1",
70
+ "tsup": "^8.3.5",
71
+ "typescript": "^5.9.3"
72
+ },
73
+ "publishConfig": {
74
+ "access": "public"
75
+ }
76
+ }