@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/dist/index.d.ts 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 };
package/dist/index.js CHANGED
@@ -1,9 +1,19 @@
1
1
  "use client";
2
- import React, { useState, useRef, useEffect, useCallback, useMemo } from 'react';
2
+ import React, { useState, useRef, useCallback, useMemo, useEffect } from 'react';
3
3
  import { Sheet } from '@academix-admin/modal-sheet';
4
- import { jsxs, jsx, Fragment } from 'react/jsx-runtime';
4
+ import { jsx, jsxs, Fragment } from 'react/jsx-runtime';
5
5
 
6
6
  // src/SelectionViewer.tsx
7
+ var RowAggregateContext = React.createContext(null);
8
+ var SelectionViewerAggregateContext = React.createContext(null);
9
+ function computeAggregateState(states) {
10
+ if (states.length === 0) return "initial";
11
+ if (states.some((s) => s === "data")) return "data";
12
+ if (states.some((s) => s === "loading")) return "loading";
13
+ if (states.every((s) => s === "empty")) return "empty";
14
+ if (states.some((s) => s === "error")) return "error";
15
+ return "initial";
16
+ }
7
17
  var getStyles = (id) => `
8
18
  #${id} .selection-viewer-header {
9
19
  padding: 0px;
@@ -188,6 +198,34 @@ var useInjectStyles = (id) => {
188
198
  };
189
199
  }, [id]);
190
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
+ };
191
229
  var SelectionViewer = ({
192
230
  id: providedId,
193
231
  isOpen,
@@ -207,9 +245,10 @@ var SelectionViewer = ({
207
245
  initialSnap = 1,
208
246
  unmountOnClose = true,
209
247
  zIndex = 1e3,
248
+ ariaLabel,
210
249
  maxHeight = "90dvh",
211
250
  minHeight = "65dvh",
212
- selectionState = "initial",
251
+ selectionState: selectionStateProp = "initial",
213
252
  closeThreshold = 0.2
214
253
  }) => {
215
254
  const [id] = useState(() => providedId || `selection-${Math.random().toString(36).substring(2, 11)}`);
@@ -223,6 +262,30 @@ var SelectionViewer = ({
223
262
  const sheetRef = useRef(null);
224
263
  useRef(null);
225
264
  useInjectStyles(id);
265
+ useModalKeys(isOpen, onClose, id);
266
+ const [reportedStates, setReportedStates] = useState(/* @__PURE__ */ new Map());
267
+ const reportAggregate = useCallback((reporterId, state) => {
268
+ setReportedStates((prev) => {
269
+ const next = new Map(prev);
270
+ next.set(reporterId, state);
271
+ return next;
272
+ });
273
+ }, []);
274
+ const unreportAggregate = useCallback((reporterId) => {
275
+ setReportedStates((prev) => {
276
+ if (!prev.has(reporterId)) return prev;
277
+ const next = new Map(prev);
278
+ next.delete(reporterId);
279
+ return next;
280
+ });
281
+ }, []);
282
+ const aggregateReporterValue = useMemo(
283
+ () => ({ report: reportAggregate, unreport: unreportAggregate }),
284
+ [reportAggregate, unreportAggregate]
285
+ );
286
+ const reportedAggregate = reportedStates.size > 0 ? computeAggregateState(Array.from(reportedStates.values())) : null;
287
+ const isComposed = reportedAggregate !== null;
288
+ const selectionState = selectionStateProp !== "initial" ? selectionStateProp : reportedAggregate ?? "initial";
226
289
  useEffect(() => {
227
290
  if (typeof window === "undefined" || !window.visualViewport) return;
228
291
  const handleResize = () => {
@@ -302,7 +365,7 @@ var SelectionViewer = ({
302
365
  [onPaginate]
303
366
  );
304
367
  if (!isOpen && unmountOnClose) return null;
305
- return /* @__PURE__ */ jsxs(
368
+ return /* @__PURE__ */ jsx(SelectionViewerAggregateContext.Provider, { value: aggregateReporterValue, children: /* @__PURE__ */ jsxs(
306
369
  Sheet,
307
370
  {
308
371
  ref: sheetRef,
@@ -317,6 +380,9 @@ var SelectionViewer = ({
317
380
  Sheet.Container,
318
381
  {
319
382
  id,
383
+ role: "dialog",
384
+ "aria-modal": "true",
385
+ "aria-label": ariaLabel,
320
386
  style: {
321
387
  maxHeight,
322
388
  minHeight: isSearchFocused ? "100dvh" : minHeight,
@@ -504,6 +570,28 @@ var SelectionViewer = ({
504
570
  },
505
571
  children: loadingProp?.view
506
572
  }
573
+ ),
574
+ isComposed && selectionState === "empty" && /* @__PURE__ */ jsx(
575
+ "div",
576
+ {
577
+ className: "selection-viewer-no-results",
578
+ style: {
579
+ padding: noResultProp?.padding ? `${noResultProp.padding.t} ${noResultProp.padding.r} ${noResultProp.padding.b} ${noResultProp.padding.l}` : "16px",
580
+ ...noResultProp?.style
581
+ },
582
+ children: noResultProp?.view || /* @__PURE__ */ jsx("div", { className: "selection-viewer-default-no-results", children: noResultProp?.text || "No results found" })
583
+ }
584
+ ),
585
+ isComposed && selectionState === "error" && /* @__PURE__ */ jsx(
586
+ "div",
587
+ {
588
+ className: "selection-viewer-error",
589
+ style: {
590
+ padding: errorProp?.padding ? `${errorProp.padding.t} ${errorProp.padding.r} ${errorProp.padding.b} ${errorProp.padding.l}` : "16px",
591
+ ...errorProp?.style
592
+ },
593
+ children: errorProp?.view || /* @__PURE__ */ jsx("div", { className: "selection-viewer-default-error", children: errorProp?.text || "No results found" })
594
+ }
507
595
  )
508
596
  ] }) : selectionState === "empty" || React.Children.count(children) <= 0 && (selectionState != "loading" && selectionState != "error") ? /* @__PURE__ */ jsx(
509
597
  "div",
@@ -544,7 +632,7 @@ var SelectionViewer = ({
544
632
  /* @__PURE__ */ jsx(Sheet.Backdrop, { onTap: backDrop ? onClose : void 0 })
545
633
  ]
546
634
  }
547
- );
635
+ ) });
548
636
  };
549
637
  var useSelectionController = (initialSelectionState) => {
550
638
  const [isOpen, setIsOpen] = useState(false);
@@ -559,7 +647,95 @@ var useSelectionController = (initialSelectionState) => {
559
647
  return [selectionId, operations, isOpen, selectionState];
560
648
  };
561
649
  var SelectionViewer_default = SelectionViewer;
650
+ function Row({ id: providedId, state = "data", onPaginate, className, style, children }) {
651
+ const aggregateReporter = React.useContext(RowAggregateContext);
652
+ const [rowId] = useState(() => providedId || `row-${Math.random().toString(36).substring(2, 11)}`);
653
+ const containerRef = useRef(null);
654
+ const isPaginating = useRef(false);
655
+ const handleScroll = useCallback(async () => {
656
+ const el = containerRef.current;
657
+ if (!el || isPaginating.current || !onPaginate) return;
658
+ const { scrollLeft, scrollWidth, clientWidth } = el;
659
+ if (scrollWidth - scrollLeft > clientWidth * 1.2) return;
660
+ isPaginating.current = true;
661
+ const hasMore = await onPaginate();
662
+ if (!hasMore) {
663
+ isPaginating.current = false;
664
+ } else {
665
+ setTimeout(() => {
666
+ isPaginating.current = false;
667
+ }, 500);
668
+ }
669
+ }, [onPaginate]);
670
+ useEffect(() => {
671
+ const el = containerRef.current;
672
+ if (!el || !onPaginate) return;
673
+ el.addEventListener("scroll", handleScroll);
674
+ return () => el.removeEventListener("scroll", handleScroll);
675
+ }, [handleScroll, onPaginate]);
676
+ useEffect(() => {
677
+ aggregateReporter?.report(rowId, state);
678
+ return () => aggregateReporter?.unreport(rowId);
679
+ }, [aggregateReporter, rowId, state]);
680
+ return /* @__PURE__ */ jsx(
681
+ "div",
682
+ {
683
+ ref: containerRef,
684
+ className: className ? `selection-viewer-row ${className}` : "selection-viewer-row",
685
+ style: {
686
+ display: "flex",
687
+ flexDirection: "row",
688
+ gap: "8px",
689
+ overflowX: "auto",
690
+ overflowY: "hidden",
691
+ ...style
692
+ },
693
+ children
694
+ }
695
+ );
696
+ }
697
+ Row.displayName = "Row";
698
+ function Column({ id: providedId, className, style, children }) {
699
+ const [columnId] = useState(
700
+ () => providedId || `column-${Math.random().toString(36).substring(2, 11)}`
701
+ );
702
+ const [reportedStates, setReportedStates] = useState(/* @__PURE__ */ new Map());
703
+ const report = useCallback((id, state) => {
704
+ setReportedStates((prev) => {
705
+ const next = new Map(prev);
706
+ next.set(id, state);
707
+ return next;
708
+ });
709
+ }, []);
710
+ const unreport = useCallback((id) => {
711
+ setReportedStates((prev) => {
712
+ if (!prev.has(id)) return prev;
713
+ const next = new Map(prev);
714
+ next.delete(id);
715
+ return next;
716
+ });
717
+ }, []);
718
+ const rowAggregateValue = useMemo(() => ({ report, unreport }), [report, unreport]);
719
+ const aggregateState = reportedStates.size > 0 ? computeAggregateState(Array.from(reportedStates.values())) : "initial";
720
+ const parentRowAggregate = React.useContext(RowAggregateContext);
721
+ const selectionViewerAggregate = React.useContext(SelectionViewerAggregateContext);
722
+ const upstreamReporter = parentRowAggregate ?? selectionViewerAggregate;
723
+ useEffect(() => {
724
+ if (!upstreamReporter) return;
725
+ upstreamReporter.report(columnId, aggregateState);
726
+ return () => upstreamReporter.unreport(columnId);
727
+ }, [upstreamReporter, columnId, aggregateState]);
728
+ return /* @__PURE__ */ jsx(RowAggregateContext.Provider, { value: rowAggregateValue, children: /* @__PURE__ */ jsx(
729
+ "div",
730
+ {
731
+ className: className ? `selection-viewer-column ${className}` : "selection-viewer-column",
732
+ style: { display: "flex", flexDirection: "column", gap: "8px", ...style },
733
+ children
734
+ }
735
+ ) });
736
+ }
737
+ Column.displayName = "Column";
562
738
 
563
- export { SelectionViewer_default as SelectionViewer, SelectionViewer_default as default, useSelectionController };
739
+ export { Column, Row, RowAggregateContext, SelectionViewer_default as SelectionViewer, SelectionViewerAggregateContext, computeAggregateState, SelectionViewer_default as default, useSelectionController };
564
740
  //# sourceMappingURL=index.js.map
565
741
  //# sourceMappingURL=index.js.map
package/dist/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/SelectionViewer.tsx"],"names":[],"mappings":";;;;;AA8GA,IAAM,SAAA,GAAY,CAAC,EAAA,KAAe;AAAA,CAAA,EAC/B,EAAE,CAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;;AAAA,CAAA,EASF,EAAE,CAAA;AAAA;AAAA;AAAA;AAAA;;AAAA,CAAA,EAMF,EAAE,CAAA;AAAA;AAAA;AAAA;AAAA;;AAAA,CAAA,EAMF,EAAE,CAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;;AAAA,CAAA,EASF,EAAE,CAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;;AAAA,CAAA,EASF,EAAE,CAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;;AAAA,CAAA,EAUF,EAAE,CAAA;AAAA;AAAA;AAAA;AAAA;AAAA;;AAAA,CAAA,EAOF,EAAE,CAAA;AAAA;AAAA;AAAA;AAAA;;AAAA,CAAA,EAMF,EAAE,CAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;;AAAA,CAAA,EAQF,EAAE,CAAA;AAAA,CAAA,EACF,EAAE,CAAA;AAAA,CAAA,EACF,EAAE,CAAA;AAAA;AAAA;AAAA;AAAA;AAAA;;AAAA,CAAA,EAOF,EAAE,CAAA;AAAA;AAAA;AAAA;;AAAA,CAAA,EAKF,EAAE,CAAA;AAAA;AAAA;AAAA;;AAAA;AAAA,CAAA,EAMF,EAAE,CAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;;AAAA,CAAA,EAUF,EAAE,CAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;;AAAA,CAAA,EAYF,EAAE,CAAA;AAAA;AAAA;;AAAA,CAAA,EAIF,EAAE,CAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;;AAAA,CAAA,EAYF,EAAE,CAAA;AAAA;AAAA;;AAAA;AAAA,CAAA,EAKF,EAAE,CAAA;AAAA;AAAA;AAAA;AAAA;AAAA;;AAAA,CAAA,EAOF,EAAE,CAAA;AAAA;AAAA;AAAA;;AAAA,CAAA,EAKF,EAAE,CAAA;AAAA;AAAA;AAAA;;;AAAA;AAAA;AAAA,GAAA,EAQA,EAAE,CAAA;AAAA;AAAA;AAAA;AAAA;;AAAA;AAAA;AAAA,GAAA,EAQF,EAAE,CAAA;AAAA;AAAA;AAAA;AAAA,CAAA;AAOP,IAAM,eAAA,GAAkB,CAAC,EAAA,KAAe;AACtC,EAAA,SAAA,CAAU,MAAM;AACd,IAAA,MAAM,OAAA,GAAU,2BAA2B,EAAE,CAAA,CAAA;AAC7C,IAAA,IAAI,QAAA,GAAW,QAAA,CAAS,cAAA,CAAe,OAAO,CAAA;AAE9C,IAAA,IAAI,CAAC,QAAA,EAAU;AACb,MAAA,QAAA,GAAW,QAAA,CAAS,cAAc,OAAO,CAAA;AACzC,MAAA,QAAA,CAAS,EAAA,GAAK,OAAA;AACd,MAAA,QAAA,CAAS,SAAA,GAAY,UAAU,EAAE,CAAA;AACjC,MAAA,QAAA,CAAS,IAAA,CAAK,YAAY,QAAQ,CAAA;AAAA,IACpC;AAGA,IAAA,OAAO,MAAM;AACX,MAAA,IAAI,QAAA,IAAY,QAAA,CAAS,IAAA,CAAK,QAAA,CAAS,QAAQ,CAAA,EAAG;AAChD,QAAA,QAAA,CAAS,IAAA,CAAK,YAAY,QAAQ,CAAA;AAAA,MACpC;AAAA,IACF,CAAA;AAAA,EACF,CAAA,EAAG,CAAC,EAAE,CAAC,CAAA;AACT,CAAA;AAGA,IAAM,kBAAkD,CAAC;AAAA,EACvD,EAAA,EAAI,UAAA;AAAA,EACJ,MAAA;AAAA,EACA,QAAA,GAAW,IAAA;AAAA,EACX,OAAA;AAAA,EACA,SAAA;AAAA,EACA,UAAA;AAAA,EACA,WAAA;AAAA,EACA,YAAA;AAAA,EACA,SAAA;AAAA,EACA,YAAA;AAAA,EACA,UAAA;AAAA,EACA,iBAAA,GAAoB,UAAA;AAAA,EACpB,QAAA;AAAA,EACA,UAAA;AAAA,EACA,UAAA,GAAa,CAAC,CAAA,EAAG,CAAC,CAAA;AAAA,EAClB,WAAA,GAAc,CAAA;AAAA,EACd,cAAA,GAAiB,IAAA;AAAA,EACjB,MAAA,GAAS,GAAA;AAAA,EACT,SAAA,GAAY,OAAA;AAAA,EACZ,SAAA,GAAY,OAAA;AAAA,EACZ,cAAA,GAAiB,SAAA;AAAA,EACjB,cAAA,GAAiB;AACnB,CAAA,KAAM;AACJ,EAAA,MAAM,CAAC,EAAE,CAAA,GAAI,QAAA,CAAS,MAAM,cAAc,CAAA,UAAA,EAAa,IAAA,CAAK,MAAA,EAAO,CAAE,SAAS,EAAE,CAAA,CAAE,UAAU,CAAA,EAAG,EAAE,CAAC,CAAA,CAAE,CAAA;AACpG,EAAA,MAAM,CAAC,WAAA,EAAa,cAAc,CAAA,GAAI,SAAS,EAAE,CAAA;AACjD,EAAA,MAAM,CAAC,eAAA,EAAiB,kBAAkB,CAAA,GAAI,SAAS,KAAK,CAAA;AAC5D,EAAA,MAAM,CAAC,cAAA,EAAgB,iBAAiB,CAAA,GAAI,SAAS,CAAC,CAAA;AACtD,EAAA,MAAM,CAAC,QAAA,EAAU,WAAW,CAAA,GAAI,SAAS,CAAC,CAAA;AAC1C,EAAA,MAAM,CAAC,eAAA,EAAiB,kBAAkB,CAAA,GAAI,SAAS,KAAK,CAAA;AAC5D,EAAA,MAAM,YAAA,GAAe,OAAO,KAAK,CAAA;AACjC,EAAA,MAAM,cAAA,GAAiB,OAAyB,IAAI,CAAA;AACpD,EAAA,MAAM,QAAA,GAAW,OAAY,IAAI,CAAA;AACjC,EAAkB,OAAuB,IAAI;AAE7C,EAAA,eAAA,CAAgB,EAAE,CAAA;AAGlB,EAAA,SAAA,CAAU,MAAM;AACd,IAAA,IAAI,OAAO,MAAA,KAAW,WAAA,IAAe,CAAC,OAAO,cAAA,EAAgB;AAE7D,IAAA,MAAM,eAAe,MAAM;AACzB,MAAA,MAAM,KAAK,MAAA,CAAO,cAAA;AAClB,MAAA,MAAM,QAAA,GAAW,MAAA,CAAO,WAAA,GAAc,EAAA,CAAG,MAAA;AACzC,MAAA,iBAAA,CAAkB,QAAA,GAAW,CAAA,GAAI,QAAA,GAAW,CAAC,CAAA;AAAA,IAC/C,CAAA;AAEA,IAAA,MAAA,CAAO,cAAA,CAAe,gBAAA,CAAiB,QAAA,EAAU,YAAY,CAAA;AAC7D,IAAA,MAAA,CAAO,cAAA,CAAe,gBAAA,CAAiB,QAAA,EAAU,YAAY,CAAA;AAE7D,IAAA,OAAO,MAAM;AACX,MAAA,MAAA,CAAO,cAAA,EAAgB,mBAAA,CAAoB,QAAA,EAAU,YAAY,CAAA;AACjE,MAAA,MAAA,CAAO,cAAA,EAAgB,mBAAA,CAAoB,QAAA,EAAU,YAAY,CAAA;AAAA,IACnE,CAAA;AAAA,EACF,CAAA,EAAG,EAAE,CAAA;AAGL,EAAA,SAAA,CAAU,MAAM;AACd,IAAA,IAAI,CAAC,MAAA,EAAQ;AACX,MAAA,cAAA,CAAe,SAAS,IAAA,EAAK;AAC7B,MAAA,cAAA,CAAe,EAAE,CAAA;AACjB,MAAA,UAAA,EAAY,WAAW,EAAE,CAAA;AACzB,MAAA,kBAAA,CAAmB,KAAK,CAAA;AACxB,MAAA;AAAA,IACF;AAAA,EACF,CAAA,EAAG,CAAC,MAAA,EAAQ,UAAA,EAAY,SAAS,CAAC,CAAA;AAElC,EAAA,MAAM,aAAA,GAAgB,YAAY,MAAM;AACtC,IAAA,IAAI,UAAA,EAAY,SAAA,IAAa,cAAA,CAAe,OAAA,EAAS;AACnD,MAAA,WAAA,CAAY,CAAA,IAAA,KAAQ,OAAO,CAAC,CAAA;AAC5B,MAAA,kBAAA,CAAmB,IAAI,CAAA;AACvB,MAAA,cAAA,CAAe,QAAQ,KAAA,EAAM;AAC7B,MAAA,cAAA,CAAe,QAAQ,KAAA,EAAM;AAAA,IAC/B;AAAA,EACF,CAAA,EAAG,CAAC,UAAA,EAAY,SAAS,CAAC,CAAA;AAE1B,EAAA,MAAM,kBAAA,GAAqB,CAAC,CAAA,KAA2C;AACrE,IAAA,MAAM,KAAA,GAAQ,EAAE,MAAA,CAAO,KAAA;AACvB,IAAA,cAAA,CAAe,KAAK,CAAA;AACpB,IAAA,UAAA,EAAY,WAAW,KAAK,CAAA;AAAA,EAC9B,CAAA;AAEA,EAAA,MAAM,oBAAoB,MAAM;AAC9B,IAAA,kBAAA,CAAmB,IAAI,CAAA;AACvB,IAAA,UAAA,EAAY,OAAA,IAAU;AACtB,IAAA,qBAAA,CAAsB,MAAM;AAC1B,MAAA,cAAA,CAAe,SAAS,KAAA,EAAM;AAAA,IAChC,CAAC,CAAA;AAAA,EACH,CAAA;AAEA,EAAA,MAAM,mBAAmB,MAAM;AAC7B,IAAA,UAAA,EAAY,MAAA,IAAS;AAAA,EACvB,CAAA;AAEA,EAAA,MAAM,uBAAuB,MAAM;AACjC,IAAA,kBAAA,CAAmB,KAAK,CAAA;AACxB,IAAA,IAAI,eAAe,OAAA,EAAS;AAC1B,MAAA,cAAA,CAAe,QAAQ,IAAA,EAAK;AAAA,IAC9B;AAAA,EACF,CAAA;AAEA,EAAA,MAAM,cAAc,MAAM;AACxB,IAAA,cAAA,CAAe,EAAE,CAAA;AACjB,IAAA,UAAA,EAAY,WAAW,EAAE,CAAA;AACzB,IAAA,IAAI,eAAe,OAAA,EAAS;AAC1B,MAAA,cAAA,CAAe,QAAQ,KAAA,EAAM;AAAA,IAC/B;AAAA,EACF,CAAA;AAEA,EAAA,MAAM,YAAA,GAAe,WAAA;AAAA,IACnB,OAAO,CAAA,KAAqC;AAC1C,MAAA,IAAI,YAAA,CAAa,OAAA,IAAW,CAAC,UAAA,EAAY;AAEzC,MAAA,MAAM,EAAE,SAAA,EAAW,YAAA,EAAc,YAAA,KAAiB,CAAA,CAAE,aAAA;AACpD,MAAA,MAAM,YAAA,GAAe,YAAA,GAAe,SAAA,IAAa,YAAA,GAAe,GAAA;AAEhE,MAAA,IAAI,YAAA,EAAc;AAChB,QAAA,YAAA,CAAa,OAAA,GAAU,IAAA;AACvB,QAAA,MAAM,OAAA,GAAU,MAAM,UAAA,EAAW;AACjC,QAAA,IAAI,CAAC,OAAA,EAAS;AACZ,UAAA,YAAA,CAAa,OAAA,GAAU,KAAA;AAAA,QACzB,CAAA,MAAO;AACL,UAAA,UAAA,CAAW,MAAM;AACf,YAAA,YAAA,CAAa,OAAA,GAAU,KAAA;AAAA,UACzB,GAAG,GAAG,CAAA;AAAA,QACR;AAAA,MACF;AAAA,IACF,CAAA;AAAA,IACA,CAAC,UAAU;AAAA,GACb;AAEA,EAAA,IAAI,CAAC,MAAA,IAAU,cAAA,EAAgB,OAAO,IAAA;AAEtC,EAAA,uBACE,IAAA;AAAA,IAAC,KAAA;AAAA,IAAA;AAAA,MACC,GAAA,EAAK,QAAA;AAAA,MACL,MAAA;AAAA,MACA,OAAA;AAAA,MACA,MAAA,EAAO,SAAA;AAAA,MACP,KAAA,EAAO,EAAE,MAAA,EAAO;AAAA,MAChB,SAAA;AAAA,MACA,SAAA,EAAW,aAAA;AAAA,MAEX,QAAA,EAAA;AAAA,wBAAA,IAAA;AAAA,UAAC,KAAA,CAAM,SAAA;AAAA,UAAN;AAAA,YACC,EAAA;AAAA,YACA,KAAA,EAAO;AAAA,cACL,SAAA;AAAA,cACA,SAAA,EAAW,kBAAkB,QAAA,GAAW,SAAA;AAAA,cACxC,QAAA,EAAU,YAAY,QAAA,IAAY,OAAA;AAAA,cAClC,MAAA,EAAQ,QAAA;AAAA,cACR,KAAA,EAAO,MAAA;AAAA,cACP,IAAA,EAAM,CAAA;AAAA,cACN,KAAA,EAAO,CAAA;AAAA,cACP,aAAA,EAAe,yCAAA;AAAA,cACf,YAAY,eAAA,GACR,UAAA,EAAY,0BAAA,IAA8B,UAAA,EAAY,kBACtD,UAAA,EAAY,eAAA;AAAA,cAChB,mBAAA,EAAqB,kBAAkB,KAAA,GAAQ,MAAA;AAAA,cAC/C,oBAAA,EAAsB,kBAAkB,KAAA,GAAQ;AAAA,aAClD;AAAA,YAEC,QAAA,EAAA;AAAA,cAAA,eAAA,mBACC,GAAA,CAAC,KAAA,CAAM,MAAA,EAAN,EACC,QAAA,kBAAA,GAAA;AAAA,gBAAC,KAAA;AAAA,gBAAA;AAAA,kBACC,SAAA,EAAU,oCAAA;AAAA,kBACV,OAAO,UAAA,EAAY,2BAAA;AAAA,kBAEnB,QAAA,kBAAA,IAAA,CAAC,KAAA,EAAA,EAAI,SAAA,EAAU,yBAAA,EAA0B,KAAA,EAAO;AAAA,oBAC9C,GAAG,UAAA,EAAY,cAAA;AAAA,oBACf,YAAY,UAAA,EAAY,UAAA;AAAA,oBACxB,SAAS,UAAA,EAAY,OAAA,GACjB,GAAG,UAAA,CAAW,OAAA,CAAQ,CAAC,CAAA,CAAA,EAAI,UAAA,CAAW,QAAQ,CAAC,CAAA,CAAA,EAAI,WAAW,OAAA,CAAQ,CAAC,IAAI,UAAA,CAAW,OAAA,CAAQ,CAAC,CAAA,CAAA,GAC/F;AAAA,mBACN,EACE,QAAA,EAAA;AAAA,oCAAA,GAAA;AAAA,sBAAC,QAAA;AAAA,sBAAA;AAAA,wBACC,SAAA,EAAU,qCAAA;AAAA,wBACV,OAAA,EAAS,oBAAA;AAAA,wBACT,YAAA,EAAW,kBAAA;AAAA,wBAEV,QAAA,EAAA,UAAA,EAAY,QAAA,oBACX,GAAA,CAAC,KAAA,EAAA,EAAI,KAAA,EAAM,IAAA,EAAK,MAAA,EAAO,IAAA,EAAK,OAAA,EAAQ,WAAA,EAAY,IAAA,EAAK,MAAA,EAAO,KAAA,EAAM,4BAAA,EAChE,QAAA,kBAAA,GAAA,CAAC,MAAA,EAAA,EAAK,CAAA,EAAE,kBAAA,EAAmB,MAAA,EAAQ,UAAA,EAAY,SAAA,IAAa,cAAA,EAAgB,WAAA,EAAY,GAAA,EAAI,aAAA,EAAc,OAAA,EAAQ,cAAA,EAAe,OAAA,EAAQ,CAAA,EAC3I;AAAA;AAAA,qBAEJ;AAAA,oCAEA,GAAA;AAAA,sBAAC,OAAA;AAAA,sBAAA;AAAA,wBAEC,GAAA,EAAK,cAAA;AAAA,wBACL,IAAA,EAAK,MAAA;AAAA,wBACL,aAAa,UAAA,EAAY,IAAA;AAAA,wBACzB,KAAA,EAAO,WAAA;AAAA,wBACP,QAAA,EAAU,kBAAA;AAAA,wBACV,SAAA,EAAW,YAAY,SAAA,IAAa,+BAAA;AAAA,wBACpC,KAAA,EAAO;AAAA,0BACL,OAAO,UAAA,EAAY,SAAA;AAAA,0BACnB,GAAG,UAAA,EAAY;AAAA,yBACjB;AAAA,wBACA,OAAA,EAAS,iBAAA;AAAA,wBACT,MAAA,EAAQ,gBAAA;AAAA,wBACR,SAAA,EAAW;AAAA,uBAAA;AAAA,sBAbN;AAAA,qBAcP;AAAA,oBAEC,WAAA,oBACC,GAAA;AAAA,sBAAC,QAAA;AAAA,sBAAA;AAAA,wBACC,SAAA,EAAU,sCAAA;AAAA,wBACV,OAAA,EAAS,WAAA;AAAA,wBACT,YAAA,EAAW,cAAA;AAAA,wBAEV,QAAA,EAAA,UAAA,EAAY,SAAA,oBACX,GAAA,CAAC,KAAA,EAAA,EAAI,KAAA,EAAM,IAAA,EAAK,MAAA,EAAO,IAAA,EAAK,OAAA,EAAQ,WAAA,EAAY,IAAA,EAAK,MAAA,EAAO,KAAA,EAAM,4BAAA,EAChE,QAAA,kBAAA,GAAA,CAAC,MAAA,EAAA,EAAK,CAAA,EAAE,sBAAA,EAAuB,MAAA,EAAQ,UAAA,EAAY,SAAA,IAAa,cAAA,EAAgB,WAAA,EAAY,GAAA,EAAI,aAAA,EAAc,OAAA,EAAQ,cAAA,EAAe,OAAA,EAAQ,CAAA,EAC/I;AAAA;AAAA;AAEJ,mBAAA,EAEJ;AAAA;AAAA,eACF,EACF,CAAA,mBAEA,IAAA,CAAC,KAAA,CAAM,QAAN,EACC,QAAA,EAAA;AAAA,gCAAA,IAAA,CAAC,KAAA,EAAA,EAAI,WAAU,yBAAA,EAEZ,QAAA,EAAA;AAAA,kBAAA,YAAA,EAAc,aAAa,MAAA,oBAC1B,GAAA;AAAA,oBAAC,QAAA;AAAA,oBAAA;AAAA,sBACC,KAAA,EAAO;AAAA,wBACL,QAAA,EAAU,UAAA;AAAA,wBACV,IAAA,EAAM,KAAA;AAAA,wBACN,GAAA,EAAK,KAAA;AAAA,wBACL,MAAA,EAAQ,MAAA;AAAA,wBACR,eAAA,EAAiB,aAAA;AAAA,wBACjB,GAAG,YAAA,CAAa;AAAA,uBAClB;AAAA,sBACA,OAAA,EAAS,aAAa,OAAA,IAAW,OAAA;AAAA,sBAEhC,QAAA,EAAA,YAAA,CAAa,IAAA,IAAQ,YAAA,CAAa,IAAA,IAAQ;AAAA;AAAA,mBAC7C;AAAA,kBAID,CAAC,eAAA,oBACA,GAAA;AAAA,oBAAC,KAAA;AAAA,oBAAA;AAAA,sBACC,SAAA,EAAU,8BAAA;AAAA,sBACV,KAAA,EAAO;AAAA,wBACL,UAAA,EAAY,YAAY,WAAA,IAAe,MAAA;AAAA,wBACvC,KAAA,EAAO,YAAY,WAAA,IAAe,MAAA;AAAA,wBAClC,YAAA,EAAc,YAAY,wBAAA,IAA4B;AAAA;AACxD;AAAA,mBACF;AAAA,kBAID,YAAA,EAAc,aAAa,OAAA,oBAC1B,GAAA;AAAA,oBAAC,QAAA;AAAA,oBAAA;AAAA,sBACC,KAAA,EAAO;AAAA,wBACL,QAAA,EAAU,UAAA;AAAA,wBACV,KAAA,EAAO,KAAA;AAAA,wBACP,GAAA,EAAK,KAAA;AAAA,wBACL,MAAA,EAAQ,MAAA;AAAA,wBACR,eAAA,EAAiB,aAAA;AAAA,wBACjB,GAAG,YAAA,CAAa;AAAA,uBAClB;AAAA,sBACA,OAAA,EAAS,aAAa,OAAA,IAAW,OAAA;AAAA,sBAEhC,QAAA,EAAA,YAAA,CAAa,IAAA,IAAQ,YAAA,CAAa,IAAA,IAAQ;AAAA;AAAA,mBAC7C;AAAA,kCAIF,GAAA,CAAC,KAAA,EAAA,EAAI,SAAA,EAAW,SAAA,CAAU,kBAAkB,4BAAA,EAC1C,QAAA,kBAAA,GAAA;AAAA,oBAAC,IAAA;AAAA,oBAAA;AAAA,sBACC,EAAA,EAAI,GAAG,EAAE,CAAA,MAAA,CAAA;AAAA,sBACT,SAAA,EAAW,UAAU,SAAA,IAAa,wBAAA;AAAA,sBAClC,KAAA,EAAO;AAAA,wBACL,YAAA,EAAc,YAAY,wBAAA,IAA4B,KAAA;AAAA,wBACtD,KAAA,EAAO,WAAW,SAAA,IAAa,OAAA;AAAA,wBAC/B,GAAG,SAAA,CAAU;AAAA,uBACf;AAAA,sBAEC,QAAA,EAAA,SAAA,CAAU;AAAA;AAAA,mBACb,EACF;AAAA,iBAAA,EACF,CAAA;AAAA,gBAGC,UAAA,oBACC,IAAA;AAAA,kBAAC,KAAA;AAAA,kBAAA;AAAA,oBACC,SAAA,EAAU,yBAAA;AAAA,oBACV,KAAA,EAAO;AAAA,sBACL,YAAY,UAAA,CAAW,UAAA;AAAA,sBACvB,SAAS,UAAA,CAAW,OAAA,GAChB,GAAG,UAAA,CAAW,OAAA,CAAQ,CAAC,CAAA,CAAA,EAAI,UAAA,CAAW,QAAQ,CAAC,CAAA,CAAA,EAAI,WAAW,OAAA,CAAQ,CAAC,IAAI,UAAA,CAAW,OAAA,CAAQ,CAAC,CAAA,CAAA,GAC/F,UAAA;AAAA,sBACJ,cAAc,UAAA,EAAY,0BAAA;AAAA,sBAC1B,GAAG,UAAA,CAAW;AAAA,qBAChB;AAAA,oBAEC,QAAA,EAAA;AAAA,sBAAA,UAAA,CAAW,UAAA,oBACV,GAAA,CAAC,MAAA,EAAA,EAAK,KAAA,EAAO,EAAE,WAAA,EAAa,UAAA,CAAW,SAAA,IAAa,KAAA,EAAM,EACvD,QAAA,EAAA,UAAA,CAAW,UAAA,EACd,CAAA;AAAA,sCAEF,GAAA;AAAA,wBAAC,OAAA;AAAA,wBAAA;AAAA,0BAEC,GAAA,EAAK,cAAA;AAAA,0BACL,IAAA,EAAK,MAAA;AAAA,0BACL,aAAa,UAAA,CAAW,IAAA;AAAA,0BACxB,KAAA,EAAO,WAAA;AAAA,0BACP,QAAA,EAAU,kBAAA;AAAA,0BACV,SAAA,EAAW,WAAW,SAAA,IAAa,+BAAA;AAAA,0BACnC,KAAA,EAAO;AAAA,4BACL,OAAO,UAAA,EAAY,SAAA;AAAA,4BACnB,GAAG,UAAA,CAAW;AAAA,2BAChB;AAAA,0BACA,OAAA,EAAS,iBAAA;AAAA,0BACT,MAAA,EAAQ,gBAAA;AAAA,0BACR,SAAA,EAAW;AAAA,yBAAA;AAAA,wBAbN;AAAA,uBAcP;AAAA,sBACC,WAAA,oBACC,GAAA;AAAA,wBAAC,QAAA;AAAA,wBAAA;AAAA,0BACC,SAAA,EAAU,sCAAA;AAAA,0BACV,OAAA,EAAS,WAAA;AAAA,0BACT,YAAA,EAAW,cAAA;AAAA,0BACX,KAAA,EAAO,EAAE,UAAA,EAAY,UAAA,CAAW,aAAa,KAAA,EAAM;AAAA,0BAElD,QAAA,EAAA,UAAA,CAAW,SAAA,IAAa,UAAA,CAAW,UAAA,oBAClC,GAAA,CAAC,KAAA,EAAA,EAAI,KAAA,EAAM,IAAA,EAAK,MAAA,EAAO,IAAA,EAAK,OAAA,EAAQ,WAAA,EAAY,IAAA,EAAK,MAAA,EAAO,KAAA,EAAM,4BAAA,EAChE,QAAA,kBAAA,GAAA,CAAC,MAAA,EAAA,EAAK,CAAA,EAAE,sBAAA,EAAuB,MAAA,EAAO,cAAA,EAAe,WAAA,EAAY,GAAA,EAAI,aAAA,EAAc,OAAA,EAAQ,cAAA,EAAe,OAAA,EAAQ,CAAA,EACpH;AAAA;AAAA,uBAEJ;AAAA,sBAED,CAAC,WAAA,IAAe,UAAA,CAAW,UAAA,wBACzB,MAAA,EAAA,EAAK,KAAA,EAAO,EAAE,UAAA,EAAY,UAAA,CAAW,SAAA,IAAa,KAAA,EAAM,EACtD,qBAAW,UAAA,EACd;AAAA;AAAA;AAAA;AAEJ,eAAA,EAEJ,CAAA;AAAA,8BAGF,GAAA,CAAC,KAAA,CAAM,OAAA,EAAN,EACC,QAAA,kBAAA,GAAA;AAAA,gBAAC,KAAA;AAAA,gBAAA;AAAA,kBACC,SAAA,EAAW,4BAA4B,iBAAiB,CAAA,CAAA;AAAA,kBACxD,QAAA,EAAU,aAAa,YAAA,GAAe,MAAA;AAAA,kBACtC,KAAA,EAAO;AAAA,oBACL,UAAA,EAAY,eAAA,GAAkB,UAAA,EAAY,0BAAA,GAA6B,GAAA;AAAA,oBACvE,eAAe,cAAA,GAAiB,CAAA,GAC5B,CAAA,EAAG,cAAA,GAAiB,EAAE,CAAA,EAAA,CAAA,GACtB;AAAA,mBACN;AAAA,kBAGC,gBAAM,QAAA,CAAS,KAAA,CAAM,QAAQ,CAAA,GAAI,oBAChC,IAAA,CAAA,QAAA,EAAA,EACG,QAAA,EAAA;AAAA,oBAAA,QAAA;AAAA,oBACA,mBAAmB,SAAA,oBAClB,GAAA;AAAA,sBAAC,KAAA;AAAA,sBAAA;AAAA,wBACC,SAAA,EAAU,0BAAA;AAAA,wBACV,KAAA,EAAO;AAAA,0BACL,SAAS,WAAA,EAAa,OAAA,GAClB,GAAG,WAAA,CAAY,OAAA,CAAQ,CAAC,CAAA,CAAA,EAAI,WAAA,CAAY,QAAQ,CAAC,CAAA,CAAA,EAAI,YAAY,OAAA,CAAQ,CAAC,IAAI,WAAA,CAAY,OAAA,CAAQ,CAAC,CAAA,CAAA,GACnG,MAAA;AAAA,0BACJ,GAAG,WAAA,EAAa;AAAA,yBAClB;AAAA,wBAEC,QAAA,EAAA,WAAA,EAAa;AAAA;AAAA;AAChB,mBAAA,EAEJ,CAAA,GACG,cAAA,KAAmB,OAAA,IAAY,KAAA,CAAM,QAAA,CAAS,KAAA,CAAM,QAAQ,CAAA,IAAK,CAAA,KAAM,cAAA,IAAkB,SAAA,IAAa,cAAA,IAAkB,OAAA,CAAA,mBAC3H,GAAA;AAAA,oBAAC,KAAA;AAAA,oBAAA;AAAA,sBACC,SAAA,EAAU,6BAAA;AAAA,sBACV,KAAA,EAAO;AAAA,wBACL,SAAS,YAAA,EAAc,OAAA,GACnB,GAAG,YAAA,CAAa,OAAA,CAAQ,CAAC,CAAA,CAAA,EAAI,YAAA,CAAa,QAAQ,CAAC,CAAA,CAAA,EAAI,aAAa,OAAA,CAAQ,CAAC,IAAI,YAAA,CAAa,OAAA,CAAQ,CAAC,CAAA,CAAA,GACvG,MAAA;AAAA,wBACJ,GAAG,YAAA,EAAc;AAAA,uBACnB;AAAA,sBAEC,QAAA,EAAA,YAAA,EAAc,wBACb,GAAA,CAAC,KAAA,EAAA,EAAI,WAAU,qCAAA,EACZ,QAAA,EAAA,YAAA,EAAc,QAAQ,kBAAA,EACzB;AAAA;AAAA,mBAEJ,GACE,mBAAmB,SAAA,mBACrB,GAAA;AAAA,oBAAC,KAAA;AAAA,oBAAA;AAAA,sBACC,SAAA,EAAU,0BAAA;AAAA,sBACV,KAAA,EAAO;AAAA,wBACL,SAAS,WAAA,EAAa,OAAA,GAClB,GAAG,WAAA,CAAY,OAAA,CAAQ,CAAC,CAAA,CAAA,EAAI,WAAA,CAAY,QAAQ,CAAC,CAAA,CAAA,EAAI,YAAY,OAAA,CAAQ,CAAC,IAAI,WAAA,CAAY,OAAA,CAAQ,CAAC,CAAA,CAAA,GACnG,MAAA;AAAA,wBACJ,GAAG,WAAA,EAAa;AAAA,uBAClB;AAAA,sBAEC,QAAA,EAAA,WAAA,EAAa;AAAA;AAAA,mBAChB,GACG,mBAAmB,OAAA,mBACtB,GAAA;AAAA,oBAAC,KAAA;AAAA,oBAAA;AAAA,sBACC,SAAA,EAAU,wBAAA;AAAA,sBACV,KAAA,EAAO;AAAA,wBACL,SAAS,SAAA,EAAW,OAAA,GAChB,GAAG,SAAA,CAAU,OAAA,CAAQ,CAAC,CAAA,CAAA,EAAI,SAAA,CAAU,QAAQ,CAAC,CAAA,CAAA,EAAI,UAAU,OAAA,CAAQ,CAAC,IAAI,SAAA,CAAU,OAAA,CAAQ,CAAC,CAAA,CAAA,GAC3F,MAAA;AAAA,wBACJ,GAAG,SAAA,EAAW;AAAA,uBAChB;AAAA,sBAEC,QAAA,EAAA,SAAA,EAAW,wBACV,GAAA,CAAC,KAAA,EAAA,EAAI,WAAU,gCAAA,EACZ,QAAA,EAAA,SAAA,EAAW,QAAQ,kBAAA,EACtB;AAAA;AAAA,mBAEJ,GACE;AAAA;AAAA,eACN,EACF;AAAA;AAAA;AAAA,SACF;AAAA,4BACC,KAAA,CAAM,QAAA,EAAN,EAAe,KAAA,EAAO,QAAA,GAAW,UAAU,MAAA,EAAW;AAAA;AAAA;AAAA,GACzD;AAEJ,CAAA;AAUA,IAAM,sBAAA,GAAyB,CAAC,qBAAA,KAK3B;AACH,EAAA,MAAM,CAAC,MAAA,EAAQ,SAAS,CAAA,GAAI,SAAS,KAAK,CAAA;AAC1C,EAAA,MAAM,CAAC,cAAA,EAAgB,iBAAiB,CAAA,GAAI,QAAA,CAAS,yBAAyB,SAAS,CAAA;AACvF,EAAA,MAAM,CAAC,WAAW,CAAA,GAAI,QAAA,CAAS,MAAM,aAAa,IAAA,CAAK,MAAA,EAAO,CAAE,QAAA,CAAS,EAAE,CAAA,CAAE,SAAA,CAAU,CAAA,EAAG,EAAE,CAAC,CAAA,CAAE,CAAA;AAE/F,EAAA,MAAM,UAAA,GAAa,QAAmB,OAAO;AAAA,IAC3C,IAAA,EAAM,MAAM,SAAA,CAAU,IAAI,CAAA;AAAA,IAC1B,KAAA,EAAO,MAAM,SAAA,CAAU,KAAK,CAAA;AAAA,IAC5B,QAAQ,MAAM,SAAA,CAAU,CAAC,IAAA,KAAS,CAAC,IAAI,CAAA;AAAA,IACvC;AAAA,GACF,CAAA,EAAI,CAAC,iBAAiB,CAAC,CAAA;AAEvB,EAAA,OAAO,CAAC,WAAA,EAAa,UAAA,EAAY,MAAA,EAAQ,cAAc,CAAA;AACzD;AAgBA,IAAO,uBAAA,GAAQ","file":"index.js","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","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"]}