@academix-admin/selection-viewer 0.1.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/README.md CHANGED
@@ -62,9 +62,40 @@ scroll container is within 20% of a viewport-height of its end):
62
62
  `noResultProp` / `errorProp` renders in place of `children`. You own fetching/filtering entirely;
63
63
  the component only renders what you hand it via `children` and this state.
64
64
 
65
- Exports: `SelectionViewer` (default), `useSelectionController`, plus every prop/type
66
- (`SelectionViewerProps`, `SelectionState`, `TitleProps`, `SearchProps`, `LoadingProps`,
67
- `NoResultProps`, `ErrorProps`, `CancelButtonProps`, `LayoutProps`, `Padding`, `SnapPoint`).
65
+ ## Composable sections: `Row` / `Column`
66
+
67
+ For sectioned lists (e.g. one horizontally-scrolling shelf per category), compose `Row`s inside a
68
+ `Column` as `SelectionViewer`'s `children`. Today's flat `children` usage is, unchanged, an
69
+ implicit `Column` with no `Row`s.
70
+
71
+ ```tsx
72
+ <SelectionViewer isOpen={isOpen} onClose={ops.close} titleProp={{ text: 'Select wallet', textColor: '#000' }}>
73
+ <Column>
74
+ <h3>Recently used</h3>
75
+ <Row state={recentState} onPaginate={loadMoreRecent}>
76
+ {recentWallets.map((w) => <WalletItem key={w.id} wallet={w} onClick={() => pick(w)} />)}
77
+ </Row>
78
+
79
+ <h3>All wallets</h3>
80
+ <Row state={allState} onPaginate={loadMoreAll}>
81
+ {allWallets.map((w) => <WalletItem key={w.id} wallet={w} onClick={() => pick(w)} />)}
82
+ </Row>
83
+ </Column>
84
+ </SelectionViewer>
85
+ ```
86
+
87
+ Unlike `@academix-admin/search-viewer`'s `Row`, this one owns no query/fetch engine —
88
+ `SelectionViewer` never had one either, so you fetch/filter yourself and tell each `Row` its own
89
+ `state` (same idea as passing `selectionState` to `SelectionViewer` today, just per-section). `Row`
90
+ triggers `onPaginate` when scrolled horizontally near its end. `Column` collects every `Row`'s
91
+ state and reports one cumulative state up to `SelectionViewer`, so `loadingProp` / `noResultProp` /
92
+ `errorProp` react automatically — no result from ANY row → the outer no-result view; any row still
93
+ loading (and none have data yet) → the outer loading view; and so on. `Column`s can nest.
94
+
95
+ Exports: `SelectionViewer` (default), `useSelectionController`, `Row`, `Column`, plus every
96
+ prop/type (`SelectionViewerProps`, `SelectionState`, `TitleProps`, `SearchProps`, `LoadingProps`,
97
+ `NoResultProps`, `ErrorProps`, `CancelButtonProps`, `LayoutProps`, `Padding`, `SnapPoint`,
98
+ `RowProps`, `ColumnProps`).
68
99
 
69
100
  ## License
70
101
 
package/dist/index.cjs CHANGED
@@ -12,6 +12,16 @@ function _interopDefault (e) { return e && e.__esModule ? e : { default: e }; }
12
12
  var React__default = /*#__PURE__*/_interopDefault(React);
13
13
 
14
14
  // src/SelectionViewer.tsx
15
+ var RowAggregateContext = React__default.default.createContext(null);
16
+ var SelectionViewerAggregateContext = React__default.default.createContext(null);
17
+ function computeAggregateState(states) {
18
+ if (states.length === 0) return "initial";
19
+ if (states.some((s) => s === "data")) return "data";
20
+ if (states.some((s) => s === "loading")) return "loading";
21
+ if (states.every((s) => s === "empty")) return "empty";
22
+ if (states.some((s) => s === "error")) return "error";
23
+ return "initial";
24
+ }
15
25
  var getStyles = (id) => `
16
26
  #${id} .selection-viewer-header {
17
27
  padding: 0px;
@@ -196,6 +206,34 @@ var useInjectStyles = (id) => {
196
206
  };
197
207
  }, [id]);
198
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
+ };
199
237
  var SelectionViewer = ({
200
238
  id: providedId,
201
239
  isOpen,
@@ -215,9 +253,10 @@ var SelectionViewer = ({
215
253
  initialSnap = 1,
216
254
  unmountOnClose = true,
217
255
  zIndex = 1e3,
256
+ ariaLabel,
218
257
  maxHeight = "90dvh",
219
258
  minHeight = "65dvh",
220
- selectionState = "initial",
259
+ selectionState: selectionStateProp = "initial",
221
260
  closeThreshold = 0.2
222
261
  }) => {
223
262
  const [id] = React.useState(() => providedId || `selection-${Math.random().toString(36).substring(2, 11)}`);
@@ -231,6 +270,30 @@ var SelectionViewer = ({
231
270
  const sheetRef = React.useRef(null);
232
271
  React.useRef(null);
233
272
  useInjectStyles(id);
273
+ useModalKeys(isOpen, onClose, id);
274
+ const [reportedStates, setReportedStates] = React.useState(/* @__PURE__ */ new Map());
275
+ const reportAggregate = React.useCallback((reporterId, state) => {
276
+ setReportedStates((prev) => {
277
+ const next = new Map(prev);
278
+ next.set(reporterId, state);
279
+ return next;
280
+ });
281
+ }, []);
282
+ const unreportAggregate = React.useCallback((reporterId) => {
283
+ setReportedStates((prev) => {
284
+ if (!prev.has(reporterId)) return prev;
285
+ const next = new Map(prev);
286
+ next.delete(reporterId);
287
+ return next;
288
+ });
289
+ }, []);
290
+ const aggregateReporterValue = React.useMemo(
291
+ () => ({ report: reportAggregate, unreport: unreportAggregate }),
292
+ [reportAggregate, unreportAggregate]
293
+ );
294
+ const reportedAggregate = reportedStates.size > 0 ? computeAggregateState(Array.from(reportedStates.values())) : null;
295
+ const isComposed = reportedAggregate !== null;
296
+ const selectionState = selectionStateProp !== "initial" ? selectionStateProp : reportedAggregate ?? "initial";
234
297
  React.useEffect(() => {
235
298
  if (typeof window === "undefined" || !window.visualViewport) return;
236
299
  const handleResize = () => {
@@ -310,7 +373,7 @@ var SelectionViewer = ({
310
373
  [onPaginate]
311
374
  );
312
375
  if (!isOpen && unmountOnClose) return null;
313
- return /* @__PURE__ */ jsxRuntime.jsxs(
376
+ return /* @__PURE__ */ jsxRuntime.jsx(SelectionViewerAggregateContext.Provider, { value: aggregateReporterValue, children: /* @__PURE__ */ jsxRuntime.jsxs(
314
377
  modalSheet.Sheet,
315
378
  {
316
379
  ref: sheetRef,
@@ -325,6 +388,9 @@ var SelectionViewer = ({
325
388
  modalSheet.Sheet.Container,
326
389
  {
327
390
  id,
391
+ role: "dialog",
392
+ "aria-modal": "true",
393
+ "aria-label": ariaLabel,
328
394
  style: {
329
395
  maxHeight,
330
396
  minHeight: isSearchFocused ? "100dvh" : minHeight,
@@ -512,6 +578,28 @@ var SelectionViewer = ({
512
578
  },
513
579
  children: loadingProp?.view
514
580
  }
581
+ ),
582
+ isComposed && selectionState === "empty" && /* @__PURE__ */ jsxRuntime.jsx(
583
+ "div",
584
+ {
585
+ className: "selection-viewer-no-results",
586
+ style: {
587
+ padding: noResultProp?.padding ? `${noResultProp.padding.t} ${noResultProp.padding.r} ${noResultProp.padding.b} ${noResultProp.padding.l}` : "16px",
588
+ ...noResultProp?.style
589
+ },
590
+ children: noResultProp?.view || /* @__PURE__ */ jsxRuntime.jsx("div", { className: "selection-viewer-default-no-results", children: noResultProp?.text || "No results found" })
591
+ }
592
+ ),
593
+ isComposed && selectionState === "error" && /* @__PURE__ */ jsxRuntime.jsx(
594
+ "div",
595
+ {
596
+ className: "selection-viewer-error",
597
+ style: {
598
+ padding: errorProp?.padding ? `${errorProp.padding.t} ${errorProp.padding.r} ${errorProp.padding.b} ${errorProp.padding.l}` : "16px",
599
+ ...errorProp?.style
600
+ },
601
+ children: errorProp?.view || /* @__PURE__ */ jsxRuntime.jsx("div", { className: "selection-viewer-default-error", children: errorProp?.text || "No results found" })
602
+ }
515
603
  )
516
604
  ] }) : selectionState === "empty" || React__default.default.Children.count(children) <= 0 && (selectionState != "loading" && selectionState != "error") ? /* @__PURE__ */ jsxRuntime.jsx(
517
605
  "div",
@@ -552,7 +640,7 @@ var SelectionViewer = ({
552
640
  /* @__PURE__ */ jsxRuntime.jsx(modalSheet.Sheet.Backdrop, { onTap: backDrop ? onClose : void 0 })
553
641
  ]
554
642
  }
555
- );
643
+ ) });
556
644
  };
557
645
  var useSelectionController = (initialSelectionState) => {
558
646
  const [isOpen, setIsOpen] = React.useState(false);
@@ -567,8 +655,101 @@ var useSelectionController = (initialSelectionState) => {
567
655
  return [selectionId, operations, isOpen, selectionState];
568
656
  };
569
657
  var SelectionViewer_default = SelectionViewer;
658
+ function Row({ id: providedId, state = "data", onPaginate, className, style, children }) {
659
+ const aggregateReporter = React__default.default.useContext(RowAggregateContext);
660
+ const [rowId] = React.useState(() => providedId || `row-${Math.random().toString(36).substring(2, 11)}`);
661
+ const containerRef = React.useRef(null);
662
+ const isPaginating = React.useRef(false);
663
+ const handleScroll = React.useCallback(async () => {
664
+ const el = containerRef.current;
665
+ if (!el || isPaginating.current || !onPaginate) return;
666
+ const { scrollLeft, scrollWidth, clientWidth } = el;
667
+ if (scrollWidth - scrollLeft > clientWidth * 1.2) return;
668
+ isPaginating.current = true;
669
+ const hasMore = await onPaginate();
670
+ if (!hasMore) {
671
+ isPaginating.current = false;
672
+ } else {
673
+ setTimeout(() => {
674
+ isPaginating.current = false;
675
+ }, 500);
676
+ }
677
+ }, [onPaginate]);
678
+ React.useEffect(() => {
679
+ const el = containerRef.current;
680
+ if (!el || !onPaginate) return;
681
+ el.addEventListener("scroll", handleScroll);
682
+ return () => el.removeEventListener("scroll", handleScroll);
683
+ }, [handleScroll, onPaginate]);
684
+ React.useEffect(() => {
685
+ aggregateReporter?.report(rowId, state);
686
+ return () => aggregateReporter?.unreport(rowId);
687
+ }, [aggregateReporter, rowId, state]);
688
+ return /* @__PURE__ */ jsxRuntime.jsx(
689
+ "div",
690
+ {
691
+ ref: containerRef,
692
+ className: className ? `selection-viewer-row ${className}` : "selection-viewer-row",
693
+ style: {
694
+ display: "flex",
695
+ flexDirection: "row",
696
+ gap: "8px",
697
+ overflowX: "auto",
698
+ overflowY: "hidden",
699
+ ...style
700
+ },
701
+ children
702
+ }
703
+ );
704
+ }
705
+ Row.displayName = "Row";
706
+ function Column({ id: providedId, className, style, children }) {
707
+ const [columnId] = React.useState(
708
+ () => providedId || `column-${Math.random().toString(36).substring(2, 11)}`
709
+ );
710
+ const [reportedStates, setReportedStates] = React.useState(/* @__PURE__ */ new Map());
711
+ const report = React.useCallback((id, state) => {
712
+ setReportedStates((prev) => {
713
+ const next = new Map(prev);
714
+ next.set(id, state);
715
+ return next;
716
+ });
717
+ }, []);
718
+ const unreport = React.useCallback((id) => {
719
+ setReportedStates((prev) => {
720
+ if (!prev.has(id)) return prev;
721
+ const next = new Map(prev);
722
+ next.delete(id);
723
+ return next;
724
+ });
725
+ }, []);
726
+ const rowAggregateValue = React.useMemo(() => ({ report, unreport }), [report, unreport]);
727
+ const aggregateState = reportedStates.size > 0 ? computeAggregateState(Array.from(reportedStates.values())) : "initial";
728
+ const parentRowAggregate = React__default.default.useContext(RowAggregateContext);
729
+ const selectionViewerAggregate = React__default.default.useContext(SelectionViewerAggregateContext);
730
+ const upstreamReporter = parentRowAggregate ?? selectionViewerAggregate;
731
+ React.useEffect(() => {
732
+ if (!upstreamReporter) return;
733
+ upstreamReporter.report(columnId, aggregateState);
734
+ return () => upstreamReporter.unreport(columnId);
735
+ }, [upstreamReporter, columnId, aggregateState]);
736
+ return /* @__PURE__ */ jsxRuntime.jsx(RowAggregateContext.Provider, { value: rowAggregateValue, children: /* @__PURE__ */ jsxRuntime.jsx(
737
+ "div",
738
+ {
739
+ className: className ? `selection-viewer-column ${className}` : "selection-viewer-column",
740
+ style: { display: "flex", flexDirection: "column", gap: "8px", ...style },
741
+ children
742
+ }
743
+ ) });
744
+ }
745
+ Column.displayName = "Column";
570
746
 
747
+ exports.Column = Column;
748
+ exports.Row = Row;
749
+ exports.RowAggregateContext = RowAggregateContext;
571
750
  exports.SelectionViewer = SelectionViewer_default;
751
+ exports.SelectionViewerAggregateContext = SelectionViewerAggregateContext;
752
+ exports.computeAggregateState = computeAggregateState;
572
753
  exports.default = SelectionViewer_default;
573
754
  exports.useSelectionController = useSelectionController;
574
755
  //# sourceMappingURL=index.cjs.map
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/SelectionViewer.tsx"],"names":["useEffect","useState","useRef","useCallback","jsxs","Sheet","jsx","Fragment","React","useMemo"],"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// ==================== 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 = \"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 // 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 <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 </>\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 );\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 };\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};\nexport default SelectionViewer;\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
@@ -1,5 +1,15 @@
1
1
  import React from 'react';
2
2
 
3
+ type AggregateReporter = {
4
+ report: (id: string, state: SelectionState) => void;
5
+ unreport: (id: string) => void;
6
+ };
7
+ /** A `Row` reports its own `state` into the nearest `Column` through this. */
8
+ declare const RowAggregateContext: React.Context<AggregateReporter | null>;
9
+ /** `Column` reports its own aggregated state up through this — `SelectionViewer` provides it and
10
+ * merges whatever's reported into its own selectionState resolution, with zero extra wiring. */
11
+ declare const SelectionViewerAggregateContext: React.Context<AggregateReporter | null>;
12
+ declare function computeAggregateState(states: SelectionState[]): SelectionState;
3
13
  type Padding = {
4
14
  l: string;
5
15
  r: string;
@@ -88,6 +98,13 @@ type SelectionViewerProps = {
88
98
  initialSnap?: number;
89
99
  unmountOnClose?: boolean;
90
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;
91
108
  maxHeight?: string;
92
109
  minHeight?: string;
93
110
  selectionState?: SelectionState;
@@ -102,4 +119,52 @@ type Operation = {
102
119
  };
103
120
  declare const useSelectionController: (initialSelectionState?: SelectionState) => [string, Operation, boolean, SelectionState];
104
121
 
105
- export { type CancelButtonProps, type ErrorProps, type LayoutProps, type LoadingProps, type NoResultProps, type Padding, type SearchProps, type SelectionState, SelectionViewer, type SelectionViewerProps, type SnapPoint, type TitleProps, SelectionViewer as default, useSelectionController };
122
+ type RowProps = {
123
+ id?: string;
124
+ /** Consumer-owned — SelectionViewer has never owned fetch/filter state, so unlike
125
+ * search-viewer's Row this isn't internally computed. Mirrors how `selectionState`
126
+ * is already a prop on SelectionViewer itself today. Defaults to "data": if you
127
+ * render children without wiring this, we assume what you rendered IS the data. */
128
+ state?: SelectionState;
129
+ /** Called when this Row is scrolled horizontally near its end. Return (or resolve to)
130
+ * `true` if more data may follow (keeps the pagination trigger armed), `false` once
131
+ * there's nothing left to fetch — mirrors SelectionViewer's own `onPaginate` contract. */
132
+ onPaginate?: () => boolean | Promise<boolean>;
133
+ className?: string;
134
+ style?: React.CSSProperties;
135
+ children?: React.ReactNode;
136
+ };
137
+ /** A horizontally-scrolling, independently-paginating section — the Row/Column
138
+ * equivalent for `SelectionViewer`. No shared code with `@academix-admin/search-viewer`'s
139
+ * Row (Library Charter: packages stay mutually independent) — this one has no
140
+ * query/debounce/cache engine of its own since `SelectionViewer` never had one either;
141
+ * the consumer owns fetching/filtering and just tells this Row what `state` it's in. */
142
+ declare function Row({ id: providedId, state, onPaginate, className, style, children }: RowProps): React.JSX.Element;
143
+ declare namespace Row {
144
+ var displayName: string;
145
+ }
146
+
147
+ type ColumnProps = {
148
+ id?: string;
149
+ className?: string;
150
+ style?: React.CSSProperties;
151
+ children?: React.ReactNode;
152
+ };
153
+ /** A vertical arrangement of `Row`s (or other content) — the explicit, composable
154
+ * equivalent of today's flat `children` list. Its default layout is deliberately
155
+ * identical to the existing `.selection-viewer-content.vertical` rendering
156
+ * (`flex-direction: column, gap: 8px`), so today's flat usage is, unchanged, "an
157
+ * implicit Column with no Rows."
158
+ *
159
+ * Provides the `RowAggregateContext` its `Row` children report into, computes ONE
160
+ * cumulative state from everything reported, and is itself a reporter one level up:
161
+ * nested inside another `Column` it reports through that Column's `RowAggregateContext`
162
+ * (behaving like a Row); at the top level it reports through `SelectionViewerAggregateContext`,
163
+ * which `SelectionViewer` provides — this drives the outer sheet's loading/empty/error
164
+ * views automatically with zero manual wiring, and lets Columns nest arbitrarily deep. */
165
+ declare function Column({ id: providedId, className, style, children }: ColumnProps): React.JSX.Element;
166
+ declare namespace Column {
167
+ var displayName: string;
168
+ }
169
+
170
+ export { type AggregateReporter, type CancelButtonProps, Column, type ColumnProps, type ErrorProps, type LayoutProps, type LoadingProps, type NoResultProps, type Padding, Row, RowAggregateContext, type RowProps, type SearchProps, type SelectionState, SelectionViewer, SelectionViewerAggregateContext, type SelectionViewerProps, type SnapPoint, type TitleProps, computeAggregateState, SelectionViewer as default, useSelectionController };