@aiquants/contact-map 0.13.0 → 0.15.0
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 +141 -16
- package/dist/client.d.mts +17 -17
- package/dist/client.d.ts +17 -17
- package/dist/client.js +2 -2
- package/dist/client.mjs +2 -2
- package/dist/styles/contact-map.standalone.css +1 -1
- package/package.json +14 -11
package/README.md
CHANGED
|
@@ -21,8 +21,8 @@ Reusable, host-agnostic business contact map and corporate directory feature pac
|
|
|
21
21
|
- **Client Layer (`@aiquants/contact-map/client`)**:
|
|
22
22
|
- Resilient NDJSON streaming client (`ContactMapStreamClient`) with keyset cursor resume, exponential backoff, and offline awareness.
|
|
23
23
|
- キーセットカーソル再開、指数バックオフ、オフライン復帰検知を備えた堅牢な NDJSON ストリームクライアント。
|
|
24
|
-
- High-performance virtualized list view with swipe gestures and
|
|
25
|
-
-
|
|
24
|
+
- High-performance virtualized list view, a keyboard listbox, with swipe gestures and long-press popups.
|
|
25
|
+
- キーボードで移れるリストボックスで、スワイプジェスチャおよび長押しのポップアップを備えた高性能仮想スクロール一覧ビュー。
|
|
26
26
|
- Dedicated background Web Worker (`treeWorkerCore`) for incremental directory tree synthesis without UI blocking.
|
|
27
27
|
- メインスレッドを阻害しない増分ディレクトリツリー合成用バックグラウンド Web Worker。
|
|
28
28
|
- Mathematical 2-column responsive layout with resize handles (`@aiquants/resize-panels`).
|
|
@@ -51,10 +51,10 @@ Peer dependencies:
|
|
|
51
51
|
"peerDependencies": {
|
|
52
52
|
"@aiquants/directory-tree": "^4.1.1",
|
|
53
53
|
"@aiquants/fuzzy-search": "^3.2.0",
|
|
54
|
-
"@aiquants/resize-panels": "^2.
|
|
55
|
-
"@aiquants/select-box": "^0.
|
|
56
|
-
"@aiquants/swipe-overlay": "^1.
|
|
57
|
-
"@aiquants/virtualscroll": "^3.
|
|
54
|
+
"@aiquants/resize-panels": "^2.2.0",
|
|
55
|
+
"@aiquants/select-box": "^0.19.0",
|
|
56
|
+
"@aiquants/swipe-overlay": "^1.4.0",
|
|
57
|
+
"@aiquants/virtualscroll": "^3.20.0",
|
|
58
58
|
"drizzle-orm": ">=1.0.0-beta.4 <2.0.0",
|
|
59
59
|
"react": ">=18",
|
|
60
60
|
"react-dom": ">=18",
|
|
@@ -115,7 +115,8 @@ The handler calls `authenticate` in one way only, `authenticate(request, { failu
|
|
|
115
115
|
`db`, `table`, `ensureConnection` and `authenticate` are required, and `createContactMapStreamHandler` / `createContactMapServer` throw a `TypeError` when `db` or `table` is missing, `table.contacted_at` is missing or is not a Drizzle column, `ensureConnection` or `authenticate` is not a function, or `firstBatchSize` / `nextBatchSize` is given but is not a number.
|
|
116
116
|
They throw a `RangeError` when `table.contacted_at` is not a `datetime2` column (`datetime2` or `datetime2(0)` to `datetime2(7)`; a `datetime`, `datetimeoffset` or `date` column is refused) or `firstBatchSize` or `nextBatchSize` is a number but not an integer from 1 to `Number.MAX_SAFE_INTEGER`.
|
|
117
117
|
Each message names the setting and ends with the value given (`[contact-map] server config authenticate must be the function that returns the request's user (…); got undefined`, `[contact-map] server config table.contacted_at must be a Drizzle datetime2 column; got "datetime"`). A stream open to everyone says so with an `authenticate` that returns a user; leaving the setting out never serves the contacts unauthenticated.
|
|
118
|
-
The handler calls `authenticate(request, { failureRedirect: null })` after checking the resume cursor (a malformed cursor gets 400 without authenticating), answers 401 when no user comes back, and sends a returned `cookie` as `Set-Cookie` on the 401 and on the stream response alike, so a session the call refreshed reaches the browser. When `authenticate` throws, the handler logs the error through `logger` and answers 500 with `{ "error": "authentication failed on the server" }`, so nothing of the session infrastructure reaches the client.
|
|
118
|
+
The handler calls `authenticate(request, { failureRedirect: null })` after checking the resume cursor (a malformed cursor gets 400 without authenticating), answers 401 when no user comes back, and sends a returned `cookie` as `Set-Cookie` on the 401 and on the stream response alike, so a session the call refreshed reaches the browser. When `authenticate` throws, the handler logs the error through `logger` and answers 500 with `{ "error": "authentication failed on the server" }`, so nothing of the session infrastructure reaches the client.
|
|
119
|
+
The stream is sent with `Cache-Control: no-store, no-transform`.
|
|
119
120
|
|
|
120
121
|
The resume cursor (`StreamCursor`: each chunk line's `nextCursor`, sent back as `cursor_contacted_at` / `cursor_person_id`) is written by the server and opaque to clients. Its `contacted_at` is the last row's value in UTC with exactly 7 fractional digits (`YYYY-MM-DDThh:mm:ss.fffffffZ`, the 100 ns of `datetime2(7)`), read from the database as text so that no digit is lost to the driver's millisecond `Date`, or `null` once the stream has reached the rows without one; its `person_id` is the last row's id, any safe integer (a signed key may be negative).
|
|
121
122
|
The chunk query checks both values by the rules below when it writes the cursor, so the next request accepts every cursor the server writes; a chunk whose last row's `person_id` is not a safe integer fails with an error naming the value.
|
|
@@ -218,13 +219,14 @@ function PrebuildContactMapTree() {
|
|
|
218
219
|
|
|
219
220
|
The components are styled with Tailwind CSS v4 utility classes: the semantic colors of a shadcn/ui-style host (`bg-background`, `text-muted-foreground`, `border-border`, ...), read from the host's `--background`, `--foreground`, ... variables (HSL components), and the `dark:` variant of a `dark` class on an ancestor.
|
|
220
221
|
|
|
221
|
-
- A host that builds with Tailwind CSS v4 generates the classes in its own build: it adds an `@source` for the package's files (`@source "<path to node_modules>/@aiquants/contact-map/dist";` for the published package), keeps the semantic colors in its `@theme`, and defines the `animate-progress-indeterminate` utility of the indeterminate progress bar (the definition below).
|
|
222
|
+
- A host that builds with Tailwind CSS v4 generates the classes in its own build, with Tailwind CSS v4.1 or later (the package's classes use the `pointer-coarse:` variant of the 16 px text of the search field and the settings' selects on touch screens and the `wrap-break-word` utility, both added in v4.1): it adds an `@source` for the package's files (`@source "<path to node_modules>/@aiquants/contact-map/dist";` for the published package), keeps the semantic colors in its `@theme`, and defines the `animate-progress-indeterminate` utility of the indeterminate progress bar (the definition below).
|
|
223
|
+
It does not import the standalone CSS as well, whose copy of the utilities would compete with its own.
|
|
222
224
|
- A host without Tailwind CSS imports `@aiquants/contact-map/styles/contact-map.standalone.css`: the package's utilities, the semantic color mapping and the progress animation, compiled. It reads the host's `--background`, ... variables at run time.
|
|
223
225
|
- Either way, the host imports the CSS of the embedded packages itself, which the standalone CSS leaves out so that an older copy baked into it never overrides the host's newer one: `@aiquants/virtualscroll/styles/virtualscroll.css`, `@aiquants/directory-tree/styles/directory-tree.css` and `@aiquants/resize-panels/styles/resize-panels.css`.
|
|
224
226
|
|
|
225
227
|
コンポーネントは Tailwind CSS v4 のユーティリティクラスで装飾する: shadcn/ui 流のホストの意味の色 (`bg-background`・`text-muted-foreground`・`border-border` など。ホストの `--background`・`--foreground` などの変数 (HSL の成分) から読む) と、祖先の `dark` クラスによる `dark:` バリアント。
|
|
226
228
|
|
|
227
|
-
- Tailwind CSS v4
|
|
229
|
+
- Tailwind CSS v4 でビルドするホストは、自分のビルドでクラスを生成する。Tailwind CSS は v4.1 以降が要る (パッケージのクラスは、タッチの画面での検索欄と設定のセレクトの 16 px の文字の `pointer-coarse:` バリアントと `wrap-break-word` ユーティリティを使い、どちらも v4.1 で加わった): パッケージのファイルへの `@source` を足し (公開版なら `@source "<node_modules への道>/@aiquants/contact-map/dist";`)、意味の色を自分の `@theme` に置き、不確定の進捗バーの `animate-progress-indeterminate` ユーティリティを定義する (定義は下)。スタンドアロンの CSS は併せて読み込まない (その写しのユーティリティが自分のものと競り合う)。
|
|
228
230
|
- Tailwind CSS を使わないホストは `@aiquants/contact-map/styles/contact-map.standalone.css` を読み込む: パッケージのユーティリティ・意味の色の対応・進捗のアニメーションをコンパイルしたもの。ホストの `--background` などの変数は実行時に読む。
|
|
229
231
|
- どちらの場合も、埋め込みのパッケージの CSS はホストが自分で読み込む (スタンドアロンの CSS は含めないので、焼き込んだ古い写しがホストの新しい CSS を上書きしない): `@aiquants/virtualscroll/styles/virtualscroll.css`・`@aiquants/directory-tree/styles/directory-tree.css`・`@aiquants/resize-panels/styles/resize-panels.css`。
|
|
230
232
|
|
|
@@ -266,14 +268,136 @@ The package reads these host CSS variables, each `0px` while the host leaves it
|
|
|
266
268
|
| `--header-height` | The list view's height (on the root element) | The list never reaches above this distance from the top of the viewport (a fixed header's height). |
|
|
267
269
|
| `--footer-height` | The list view's height (on the root element) | Taken from the bottom of the viewport (a fixed footer's height). |
|
|
268
270
|
| `--scrollbar-height` | The list view's height (on the root element) | Taken from the bottom of the viewport as well (room kept for a horizontal scrollbar). |
|
|
269
|
-
| `--aqcm-overlay-right` | The
|
|
271
|
+
| `--aqcm-overlay-right` | The long-press popup and the swipe overlay | Their right inset, such as the width of a menu pinned to the right edge: `:root { --aqcm-overlay-right: var(--my-pinned-menu-width, 0px); }`. |
|
|
270
272
|
|
|
271
273
|
| 変数 | 読むもの | 意味 |
|
|
272
274
|
| --- | --- | --- |
|
|
273
275
|
| `--header-height` | 一覧ビューの高さ (ルート要素で読む) | 一覧はビューポートの上端からこの距離より上へ出ない (固定したヘッダーの高さ)。 |
|
|
274
276
|
| `--footer-height` | 一覧ビューの高さ (ルート要素で読む) | ビューポートの下端から差し引く (固定したフッターの高さ)。 |
|
|
275
277
|
| `--scrollbar-height` | 一覧ビューの高さ (ルート要素で読む) | 同じくビューポートの下端から差し引く (横のスクロールバーのために空ける高さ)。 |
|
|
276
|
-
| `--aqcm-overlay-right` |
|
|
278
|
+
| `--aqcm-overlay-right` | 長押しのポップアップとスワイプのオーバーレイ | 右端の余白 (右端にピン留めしたメニューの幅など): `:root { --aqcm-overlay-right: var(--my-pinned-menu-width, 0px); }`。 |
|
|
279
|
+
|
|
280
|
+
## Pointer Targets / ポインターの的
|
|
281
|
+
|
|
282
|
+
Every control the package draws is a target of at least 44 × 44 CSS px under every pointer (a mouse, a pen, a finger), WCAG 2.2's enhanced target size (SC 2.5.5, AAA): the search band's and the settings and statistics tabs' below, the header annotation's retry button, and the detail panel's and the long-press popup's (see their sections).
|
|
283
|
+
パッケージが描く操作部品は、どのポインター (マウス・ペン・指) でも 44 × 44 CSS px 以上の的で、WCAG 2.2 の拡張の的の大きさ (SC 2.5.5、AAA) を満たす。下の検索の帯と検索設定・検索統計のタブ、ヘッダーの注記の再試行のボタン、詳細パネルと長押しのポップアップ (それぞれの節を参照) のもの。
|
|
284
|
+
|
|
285
|
+
- **The search band:** the tabs of the search page (fuzzy search, settings, statistics), the AND / OR switch, the search field and its clear button, the list / tree tabs, and the tree view's controls beside them (the whole-company switch, expand all, collapse all). The row of the list / tree tabs wraps, so on a narrow screen the tree view's controls take a line of their own instead of running past the screen's edge.
|
|
286
|
+
- **The settings and statistics tabs:** their buttons (reset all, reset, rebuild index) and inner tabs are 44 × 44 px, and the selects 44 px high. A slider's box is 44 px high over its width, and a press anywhere on it moves the value; the thumb keeps the browser's drawing. A checkbox keeps its drawn 12 px box, and the label row around it, 44 px high over the panel's width, is its target: a press anywhere on the row toggles it.
|
|
287
|
+
- **Touch screens:** under a coarse pointer the text of the search field and the settings' selects is 16 px, so iOS Safari does not zoom the page when one of them takes the focus.
|
|
288
|
+
- **Names and states:** the clear button is named by `clearSearch` while it can clear (while a search runs, its visible `searching` text names it); the list / tree buttons report the shown view with `aria-pressed`; the statistics tabs are tabs of a tab list named by `statsTabsLabel`, as the settings tabs are of one named by `settingsTabsLabel`, the shown one selected.
|
|
289
|
+
- **Their own sizes:** the resize handles between the list or the tree and the detail pane keep their thin band, and the keyboard resizes the panes (`@aiquants/resize-panels`); the scroll controls of the list and the tree (`@aiquants/virtualscroll`, pointer-only) and the tree's rows (`@aiquants/directory-tree`) follow those packages.
|
|
290
|
+
|
|
291
|
+
- **検索の帯**: 検索ページのタブ (あいまい検索・検索設定・検索統計)・AND / OR の切り替え・検索欄とクリアのボタン・一覧 / ツリーのタブ・その横のツリーのビューの操作部品 (会社全体の表示の切り替え・全展開・全折りたたみ)。一覧 / ツリーのタブの行は折り返すので、狭い画面ではツリーのビューの操作部品は画面の端からはみ出さずに次の行へ移る。
|
|
292
|
+
- **検索設定と検索統計のタブ**: ボタン (すべてリセット・リセット・インデックス再構築) と内側のタブは 44 × 44 px、セレクトは高さ 44 px。スライダーは幅いっぱいで高さ 44 px の箱を持ち、箱のどこを押しても値が動く (つまみの描き方はブラウザーのまま)。チェックボックスは描く箱を 12 px のまま保ち、それを囲むパネルの幅いっぱいで高さ 44 px のラベルの行が的になる (行のどこを押しても切り替わる)。
|
|
293
|
+
- **タッチの画面**: 粗いポインターでは検索欄と設定のセレクトの文字を 16 px にし、フォーカスを受けても iOS の Safari が画面を拡大しない。
|
|
294
|
+
- **名前と状態**: クリアのボタンは消せる間 `clearSearch` を名前に持つ (検索中は見えている `searching` の文字が名前)。一覧 / ツリーのボタンは見せているビューを `aria-pressed` で示す。検索統計の内側のタブは `statsTabsLabel` を名前に持つタブの並びのタブで (検索設定のタブが `settingsTabsLabel` の並びのタブであるのと同じ)、見せているものが選ばれている。
|
|
295
|
+
- **自分の大きさを保つもの**: 一覧やツリーと詳細のペインの間のサイズ変更ハンドルは細い帯のままで、ペインの幅はキーボードでも変えられる (`@aiquants/resize-panels`)。一覧とツリーのスクロールの操作部品 (`@aiquants/virtualscroll`。ポインター専用) とツリーの行 (`@aiquants/directory-tree`) はそれぞれのパッケージに従う。
|
|
296
|
+
|
|
297
|
+
## Mobile Detail Overlay / モバイルの詳細オーバーレイ
|
|
298
|
+
|
|
299
|
+
When the list or the tree view is a single column (narrower than its two-column threshold), choosing a contact opens its details in an overlay, `SwipeOverlay`: a panel at the right edge, which renders the platform's modal dialog through `@aiquants/swipe-overlay`'s `useSwipeOverlayDialog`.
|
|
300
|
+
一覧かツリーのビューが 1 カラム (2 カラムの閾値より狭い) のとき、連絡先を選ぶと詳細がオーバーレイ `SwipeOverlay` (右端の面) で開く。オーバーレイは `@aiquants/swipe-overlay` の `useSwipeOverlayDialog` でプラットフォームのモーダルなダイアログを描く。
|
|
301
|
+
|
|
302
|
+
- **While it is open** the rest of the page is inert (a pinned side menu outside the content area included), and the focus starts on the overlay's heading (the `title` prop, `overlayTitle` by default), which names the dialog. Tab moves through the dialog and never reaches the page behind it; the browser's own chrome may take the focus after the last control, as with any modal dialog.
|
|
303
|
+
- **It closes** by a swipe to the right that starts anywhere on the panel (a drag past 120 px, or a flick), a tap on the dimmed backdrop (on the tap's click, so the tap presses nothing the backdrop covers), the close button, Escape (not one that cancels an IME conversion) and the platform's close request (Android's Back). Every way goes through the same close path.
|
|
304
|
+
- **It leaves** by sliding out to the right, from wherever the finger released it, while the backdrop fades; it unmounts `SWIPE_OVERLAY_EXIT_MS` (300 ms) after it closed. With `prefers-reduced-motion: reduce` it leaves without a transition. In both views the overlay's open state ends with the overlay: one that unmounts while open (its contact leaves the list or the tree, or the layout leaves the single column) never comes back open by itself, and a tap in two columns does not open it later.
|
|
305
|
+
In the tree view a rebuild that moves the selected contact to another path keeps the open overlay mounted on the same contact, without opening it again or moving the focus.
|
|
306
|
+
- **Touch:** the panel and the backdrop take `touch-action: pinch-zoom` (`SWIPE_OVERLAY_PANEL_TOUCH_ACTION`), so a pinch zooms the page, a horizontal move is the swipe and a vertical move on the header or the backdrop pulls nothing (no pull-to-refresh).
|
|
307
|
+
Every vertical scroll area takes `SWIPE_OVERLAY_SCROLL_AREA_STYLE`: `touch-action: pan-y pinch-zoom`, and `overscroll-behavior-y: contain`, so its scroll never chains to the page behind. A scroll container resets the touch-action it inherits, so content placed in `SwipeOverlay` gives each of its own vertical scroll areas that style, as the detail panel's tab contents do; a swipe does not start on an element the browser pans sideways (one that scrolls horizontally and whose touch-action allows that).
|
|
308
|
+
- **Targets and contrast:** the close button is at least 44 × 44 px, the detail panel's tabs, copy buttons and value links (an address, a number, a URL; each padded above and below by half of what its line box lacks of 44 px, `max(0px, (2.75rem - 1lh) / 2)`, and at least 44 px wide, so a short value is no narrower a target) are 44 px under every pointer (WCAG 2.2 enhanced target size), value links and copy buttons show a 2 px focus ring under the keyboard, the four tabs share the width equally so they fit a phone, long values wrap instead of scrolling sideways,
|
|
309
|
+
and every text keeps 7:1 against its ground in the light and the dark scheme.
|
|
310
|
+
- **Requirements:** the platform's `<dialog>` with `showModal()` (Chromium 37, Firefox 98, Safari 15.4) and `inert` (Chromium 102, Firefox 112, Safari 15.5). The overlay's right edge follows `--aqcm-overlay-right` (see Styling).
|
|
311
|
+
|
|
312
|
+
- **開いている間** はページのほか (内容の領域の外にピン留めしたサイドメニューを含む) は不活性で、フォーカスはダイアログの名前になるオーバーレイの見出し (`title` prop。既定は `overlayTitle`) から始まる。Tab はダイアログの中に留まり、背後のページへは行かない。どのモーダルなダイアログとも同じく、最後の操作部品の後はブラウザ自身の枠がフォーカスを取ることがある。
|
|
313
|
+
- **閉じる** のは、面のどこからでも始まる右へのスワイプ (120 px を超える引き、またははじき)、暗くした背景のタップ (タップの click で閉じるので、背景の下のものは押さない)、閉じるボタン、Escape (IME の変換を取り消すものを除く)、プラットフォームの閉じる要求 (Android の戻る)。どれも同じ閉じる経路を通る。
|
|
314
|
+
- **去る** ときは、指を離した所から右へ滑り出し、背景は薄れる。閉じてから `SWIPE_OVERLAY_EXIT_MS` (300 ms) 後にアンマウントする。`prefers-reduced-motion: reduce` では遷移なしで去る。どちらのビューでもオーバーレイの開いた状態はオーバーレイとともに終わる。開いたままアンマウントしたもの (連絡先が一覧かツリーを出たか、配置が 1 カラムを出た) は自分から開いて戻らず、2 カラムのタップも後でオーバーレイを開かない。ツリービューでは、選んだ連絡先を別のパスへ動かす作り直しでも、開いたオーバーレイは同じ連絡先のまま付いていて、開き直しもフォーカスの移動もしない。
|
|
315
|
+
- **タッチ**: 面と背景は `touch-action: pinch-zoom` (`SWIPE_OVERLAY_PANEL_TOUCH_ACTION`) を取るため、ピンチはページを拡大し、横の動きはスワイプになり、ヘッダーや背景の上の縦の動きは何も引っ張らない (引いて再読み込みにならない)。縦のスクロール領域はどれも `SWIPE_OVERLAY_SCROLL_AREA_STYLE` (`touch-action: pan-y pinch-zoom` と `overscroll-behavior-y: contain`) を取り、そのスクロールは背後のページへつながらない。スクロールの容器は受け継いだ touch-action を解くので、`SwipeOverlay` に置く内容は、詳細パネルのタブの中身と同じく、自分の縦のスクロール領域それぞれにそのスタイルを与える。ブラウザーが横にパンする要素 (横にスクロールし、touch-action がそれを許すもの) からはスワイプが始まらない。
|
|
316
|
+
- **的とコントラスト**: 閉じるボタンは少なくとも 44 × 44 px、詳細パネルのタブ・コピーのボタン・値のリンク (アドレス・番号・URL。行の箱が 44 px に足りない分の半分 `max(0px, (2.75rem - 1lh) / 2)` を上下に足し、幅は少なくとも 44 px なので、短い値も細い的にならない) はどのポインターでも 44 px (WCAG 2.2 の拡張の的の大きさ)。
|
|
317
|
+
値のリンクとコピーのボタンはキーボードのフォーカスで 2 px の輪を描く。4 つのタブは幅を等分してスマートフォンにも収まり、長い値は横にスクロールさせずに折り返し、どの文字も明暗どちらの配色でも地に対して 7:1 を保つ。
|
|
318
|
+
- **前提**: プラットフォームの `<dialog>` の `showModal()` (Chromium 37・Firefox 98・Safari 15.4) と `inert` (Chromium 102・Firefox 112・Safari 15.5)。オーバーレイの右端は `--aqcm-overlay-right` に従う (スタイルの節を参照)。
|
|
319
|
+
|
|
320
|
+
## Long-Press Popup / 長押しのポップアップ
|
|
321
|
+
|
|
322
|
+
A long press on a contact in the list or the tree view (held for 600 ms without moving more than 8 px) opens a popup with the contact's name and affiliation, its phone numbers and email addresses (each a link with a copy button) and the last contact date; it never opens the single-column detail overlay, which only a tap opens. The popup, `ContactDetailPopup`, renders the platform's modal dialog through `@aiquants/swipe-overlay`'s `useOverlayDialog`, portalled to `document.body`.
|
|
323
|
+
一覧かツリーのビューで連絡先を長押しする (8 px より動かさずに 600 ms 押し続ける) と、連絡先の名前と所属・電話番号とメールアドレス (それぞれリンクとコピーのボタン)・最終の連絡日を見せるポップアップが開く。1 カラムの詳細のオーバーレイは開かない (開くのはタップだけ)。ポップアップ `ContactDetailPopup` は `@aiquants/swipe-overlay` の `useOverlayDialog` でプラットフォームのモーダルなダイアログを描き、`document.body` へポータルする。
|
|
324
|
+
|
|
325
|
+
- **While it is open** it sits in the top layer, above any `z-index` of the host, and the rest of the page is inert (a pinned side menu outside the content area included). The focus starts on its heading, the contact's name, which names the dialog, and returns to where it was when the popup closes; Tab moves through the popup and never reaches the page behind it. No event inside the popup reaches the React handlers of the row or the tree that opened it, and the body's text selection stays off.
|
|
326
|
+
The popup stops those events through React at its dialog, which also ends their native propagation at `document.body`, the portal's container: capture-phase listeners on the window and the document, and listeners on the body itself, still see them, while bubble-phase listeners on the document and the window do not.
|
|
327
|
+
- **It closes** on a tap on the dimmed backdrop (on the tap's click, so the tap presses nothing the backdrop covers), the close button, Escape (not one that cancels an IME conversion) and the platform's close request (Android's Back). A wheel or a finger move does not close it.
|
|
328
|
+
- **The release:** a browser may turn the release of the long press into mouse events at the release point, where the backdrop now lies (Chromium hit-tests it again). `useLongPressPopup` consumes the release's `mousedown`, `mouseup` and `click` on the window's capture phase, wherever they land, so no other listener on the page receives them and the popup neither loses its focus nor closes; the click ends the wait, and so does the next press or key (a browser that sends no click).
|
|
329
|
+
- **Layout:** the card is centred in the content area, 16 px from its sides and 24 px from its top and bottom, at most 28rem wide, and scrolls inside when it is taller than the screen. The backdrop dims the page with slate-900 at 50 %, as the detail overlay's does, and the popup's right edge follows `--aqcm-overlay-right` (see Styling).
|
|
330
|
+
- **Gmail:** while `openEmailsWithGmail` is on, a double click on an email address, or two taps within 350 ms, opens Gmail's compose window, as the `popupGmailHint` label says.
|
|
331
|
+
- **Targets:** its links, copy buttons and close button are 44 px targets under every pointer and show the package's 2 px focus ring under the keyboard.
|
|
332
|
+
- **Requirements:** the same as the detail overlay's, the platform's `<dialog>` with `showModal()` and `inert`.
|
|
333
|
+
|
|
334
|
+
- **開いている間** は最前面の層 (top layer) にあってホストのどの `z-index` よりも上に描かれ、ページのほか (内容の領域の外にピン留めしたサイドメニューを含む) は不活性になる。フォーカスはダイアログの名前になる見出し (連絡先の名前) から始まり、閉じると開く前の所へ戻る。Tab はポップアップの中を移り、背後のページへは行かない。ポップアップの中のイベントは、開いた行やツリーの React の処理へ届かず、body の文字の選択は止まる。ポップアップはそれらのイベントをダイアログで React を通して止め、ネイティブの伝播もポータルの容器の `document.body` で終わる。窓と文書の捕獲段の受け口と body 自身の受け口はイベントを見るが、文書と窓のバブリング段の受け口は見ない。
|
|
335
|
+
- **閉じる** のは、暗くした背景のタップ (タップの click で閉じるので、背景の下のものは押さない)、閉じるボタン、Escape (IME の変換を取り消すものを除く)、プラットフォームの閉じる要求 (Android の戻る)。ホイールや指の移動では閉じない。
|
|
336
|
+
- **離したとき**: 長押しを離すと、その点 (いまは背景がある) にマウスのイベントを出すブラウザーがある (Chromium は当たり判定し直す)。`useLongPressPopup` は、離したときの `mousedown`・`mouseup`・`click` を、どこに届くものでも窓の捕獲段で飲むので、ページのほかの受け口はそれらを受けず、ポップアップはフォーカスを失わず閉じもしない。待ちは click で終わり、次の押下かキーでも終わる (click を出さないブラウザー)。
|
|
337
|
+
- **配置**: カードは内容の領域の中央に、左右から 16 px、上下から 24 px 離して置き、幅は最大 28rem。画面より高ければ中でスクロールする。背景は詳細のオーバーレイと同じく半分の不透明度の slate-900 でページを暗くし、ポップアップの右端は `--aqcm-overlay-right` に従う (スタイルの節を参照)。
|
|
338
|
+
- **Gmail**: `openEmailsWithGmail` が有効な間は、メールアドレスのダブルクリックか 350 ms 以内の 2 度のタップで Gmail の作成画面を開く (`popupGmailHint` のラベルが告げるとおり)。
|
|
339
|
+
- **的**: リンク・コピーのボタン・閉じるボタンはどのポインターでも 44 px の的で、キーボードのフォーカスではパッケージの 2 px の輪を描く。
|
|
340
|
+
- **前提**: 詳細のオーバーレイと同じく、プラットフォームの `<dialog>` の `showModal()` と `inert`。
|
|
341
|
+
|
|
342
|
+
## List Keyboard / 一覧のキーボード
|
|
343
|
+
|
|
344
|
+
The list view's list is a `listbox` on VirtualScroll's content element, named by the `listboxLabel` label and described by the hidden `listKeyboardHelp` text. The rows never take the focus, so the listbox is their Tab stop, and the only one: the listbox scrolls the list with its own keys, so VirtualScroll's scroll controls beside it (the scroll bar and the scroll-to-edge pills) are pointer-only, as a native scrollbar is (`enableArrowButtonTabStops: false`; the tree view's are too, since the tree's own keys keep the focused row in view).
|
|
345
|
+
Each row is an `option` with `aria-selected`, `aria-posinset` / `aria-setsize` (its place in the whole list, since only some rows are rendered) and the id `virtualScrollItemElementId(listboxId, personId)`; the listbox's `aria-activedescendant` names the active option, the row the keyboard is on (VirtualScroll's active item, `activeItemIndex`).
|
|
346
|
+
一覧ビューの一覧は VirtualScroll の中身の要素に置いた `listbox` で、`listboxLabel` のラベルが名前を、見せない `listKeyboardHelp` の文が説明を与える。行はフォーカスを受けないので、リストボックスが行の Tab の止まり先で、一覧の止まり先はそれだけ。リストボックスが自分のキーで一覧をスクロールするので、隣の VirtualScroll のスクロールの操作部品 (スクロールバーと端へ戻るピル) はネイティブのスクロールバーと同じくポインター専用 (`enableArrowButtonTabStops: false`。ツリービューのものも同じで、ツリー自身のキーがフォーカスのある行を見せ続ける)。行はそれぞれ `option` で、`aria-selected`・`aria-posinset` / `aria-setsize` (描くのは一部の行だけなので、一覧全体の中の位置)・id `virtualScrollItemElementId(listboxId, personId)` を持つ。リストボックスの `aria-activedescendant` は、キーボードがいる行であるアクティブな選択肢を名指す (VirtualScroll のアクティブな項目 `activeItemIndex`)。
|
|
347
|
+
|
|
348
|
+
| Key | Action |
|
|
349
|
+
| --- | --- |
|
|
350
|
+
| ArrowDown / ArrowUp | Moves the active option one row. |
|
|
351
|
+
| PageDown / PageUp | Moves it by a screen of whole rows: the viewport's height divided by the 64 px row, rounded down, at least 1. |
|
|
352
|
+
| Home / End | Moves it to the first / the last row. |
|
|
353
|
+
| Enter / Space | Selects the active contact and opens its details: the overlay in a single column, the pane in two columns. |
|
|
354
|
+
|
|
355
|
+
| キー | 動き |
|
|
356
|
+
| --- | --- |
|
|
357
|
+
| ArrowDown / ArrowUp | アクティブな選択肢を 1 行移す。 |
|
|
358
|
+
| PageDown / PageUp | 表示域に丸ごと入る行の数 (表示域の高さを 64 px の行で割って切り捨て、少なくとも 1) だけ移す。 |
|
|
359
|
+
| Home / End | 先頭 / 末尾の行へ移す。 |
|
|
360
|
+
| Enter / Space | アクティブな連絡先を選び、詳細を開く (1 カラムではオーバーレイ、2 カラムでは右の区画)。 |
|
|
361
|
+
|
|
362
|
+
- **Moves** stop at the ends (they never wrap) and reveal the row at the nearest edge of the viewport (`scrollToIndex(index, { align: "nearest" })`). While no option is active, every move key (End included) makes the start option active instead: the selected contact's row, or the first row. A key with a modifier (Alt, Ctrl, Meta or Shift) and a key of an IME composition do nothing.
|
|
363
|
+
- **Selection** does not follow the active option: only Enter, Space, a tap and a long press select a contact. When the listbox takes the keyboard's focus (`:focus-visible`) without an active option, the selected contact's row, or the first row, becomes active without scrolling; a pointer's focus makes no option active by itself, and the click that follows makes the pressed row active. A tap or a long press makes its row active, so the keyboard goes on from the row the pointer chose.
|
|
364
|
+
The active option is kept by contact: a search that narrows the list keeps it on the same contact, and there is none once the search drops that contact.
|
|
365
|
+
- **Focus indicator:** while the listbox shows the keyboard focus, the active option draws the package's 2 px focus ring (blue-700, sky-300 in the dark scheme) inside the row's edge, where the next row cannot cover it and the list's clipping cannot cut it. While the active row lies outside the viewport, VirtualScroll's own focus ring on the list shows instead.
|
|
366
|
+
- **Empty list:** while the list has no rows, the active option is switched off and the list keeps its empty state.
|
|
367
|
+
- **Popups:** while a long-press popup is open the page is inert and the focus is inside the popup, so no key reaches the list, and pointer drag scrolling stops.
|
|
368
|
+
|
|
369
|
+
- **移動** は端で止まり (回り込まない)、移した行を表示域の近い方の端へ入れる (`scrollToIndex(index, { align: "nearest" })`)。アクティブな選択肢が無い間は、どの移動のキーも (End も) 代わりに始まりの選択肢 (選んだ連絡先の行、無ければ先頭の行) をアクティブにする。修飾キー (Alt・Ctrl・Meta・Shift) 付きのキーと IME の変換のキーは何もしない。
|
|
370
|
+
- **選択** はアクティブな選択肢に付いて動かない。連絡先を選ぶのは Enter・Space・タップ・長押しだけ。アクティブな選択肢の無いリストボックスがキーボードのフォーカス (`:focus-visible`) を受けると、選んだ連絡先の行 (無ければ先頭の行) をスクロールせずにアクティブにする。ポインターのフォーカスはそれだけでは何もアクティブにせず、続く click が押した行をアクティブにする。タップと長押しはその行をアクティブにするので、キーボードはポインターが選んだ行から続く。アクティブな選択肢は連絡先で持つので、検索の絞り込みで並びが変わっても同じ連絡先に残り、絞り込みがその連絡先を落とせば無くなる。
|
|
371
|
+
- **フォーカスの印**: リストボックスがキーボードのフォーカスを見せる間、アクティブな選択肢はパッケージの 2 px のフォーカスの輪 (blue-700、暗い配色は sky-300) を行の縁の内側に描く (次の行に覆われず、一覧の切り取りにも切られない)。アクティブな行が表示域の外にある間は、代わりに VirtualScroll 自身の一覧のフォーカスの輪が出る。
|
|
372
|
+
- **空の一覧**: 行が無い間はアクティブな選択肢の仕組みを切り、今の空の表示のままにする。
|
|
373
|
+
- **ポップアップ**: 長押しのポップアップが開いている間はページが不活性でフォーカスはポップアップの中にあるため、どのキーも一覧へ届かず、ポインターのドラッグのスクロールも止まる。
|
|
374
|
+
|
|
375
|
+
## DOM Hooks / DOM のフック
|
|
376
|
+
|
|
377
|
+
Hosts and their tests find the package's overlays and the list's state by these attributes; the class names are styling and change freely.
|
|
378
|
+
ホストとその試験は、パッケージのオーバーレイと一覧の状態を次の属性で見つける。クラス名は見た目のためのもので、自由に変わる。
|
|
379
|
+
|
|
380
|
+
| Attribute | Element |
|
|
381
|
+
| --- | --- |
|
|
382
|
+
| `data-testid="contact-map-mobile-overlay"` | The detail overlay's `<dialog>` |
|
|
383
|
+
| `data-contact-map-overlay-backdrop` | The detail overlay's backdrop |
|
|
384
|
+
| `data-contact-map-overlay-panel` | The detail overlay's panel |
|
|
385
|
+
| `data-contact-popup-root` | The long-press popup's `<dialog>` |
|
|
386
|
+
| `data-contact-popup-backdrop` | The long-press popup's backdrop |
|
|
387
|
+
| `data-contact-popup-card` | The long-press popup's card |
|
|
388
|
+
| `data-selected` (`"true"` / `"false"`) | A list row: whether it is the selected contact, as its `aria-selected` says |
|
|
389
|
+
| `data-contact-map-row-active` | The list's active option, the row the keyboard is on |
|
|
390
|
+
|
|
391
|
+
| 属性 | 要素 |
|
|
392
|
+
| --- | --- |
|
|
393
|
+
| `data-testid="contact-map-mobile-overlay"` | 詳細のオーバーレイの `<dialog>` |
|
|
394
|
+
| `data-contact-map-overlay-backdrop` | 詳細のオーバーレイの背景 |
|
|
395
|
+
| `data-contact-map-overlay-panel` | 詳細のオーバーレイの面 |
|
|
396
|
+
| `data-contact-popup-root` | 長押しのポップアップの `<dialog>` |
|
|
397
|
+
| `data-contact-popup-backdrop` | 長押しのポップアップの背景 |
|
|
398
|
+
| `data-contact-popup-card` | 長押しのポップアップのカード |
|
|
399
|
+
| `data-selected` (`"true"` / `"false"`) | 一覧の行。選んだ連絡先か (`aria-selected` と同じ) |
|
|
400
|
+
| `data-contact-map-row-active` | 一覧のアクティブな選択肢 (キーボードがいる行) |
|
|
277
401
|
|
|
278
402
|
## Search Normalization / 検索語の正規化
|
|
279
403
|
|
|
@@ -310,7 +434,8 @@ The typed query is used because normalization can drop a spelling it holds. The
|
|
|
310
434
|
- 混在テキスト・数字や記号・完全には読めない語は全角/半角・かな・大文字小文字の形のままで、そのテキストのほかのキーワードも同じ (`user@example.com`、`営業部 tanaka`、`tanaka1`、`ke-su`、`sony`、`"yamada taro" sony`)。
|
|
311
435
|
- キーワードは fuzzy-search の `formatQuerySets` で書き戻す: キーワードの間は 1 つの空白、空白を持つキーワードは ASCII の引用符で囲み (`"ABC 商事"` → `"abc 商事"`)、空のキーワードと、正規化で先のキーワードと等しくなったキーワードは書かない。そのため `parseQuerySets` は検索語からちょうどこれらのキーワードを読む。引用符の無いテキストは、空白で区切った各語を上のとおり正規化して 1 度ずつ並べ、1 つの空白で区切ったものになる。
|
|
312
436
|
|
|
313
|
-
検索結果のハイライトと完全一致による並べ替えは、入力されたままのテキストからの 1 つの導出。`createSearchQueryPattern(query)` は `getSearchQuerySpellings(query)` が並べる表記 (テキストのキーワードとその正規化形のキーワードの各語に対する select-box の `getNormalizedVariants`。語は fuzzy-search の `parseQuerySets` で読むため、引用符は表記の一部にならない。どの仮名も半角の形を持つ表記には、続けて半角カナの表記を置く:
|
|
437
|
+
検索結果のハイライトと完全一致による並べ替えは、入力されたままのテキストからの 1 つの導出。`createSearchQueryPattern(query)` は `getSearchQuerySpellings(query)` が並べる表記 (テキストのキーワードとその正規化形のキーワードの各語に対する select-box の `getNormalizedVariants`。語は fuzzy-search の `parseQuerySets` で読むため、引用符は表記の一部にならない。どの仮名も半角の形を持つ表記には、続けて半角カナの表記を置く:
|
|
438
|
+
`タナカ` の次に `タナカ`、`サトウ` の次に `サトウ`。保存されたフィールドに多い形) を、最長のものから大文字小文字を区別せずに探す。`HighlightedText` はその一致に `mark` 要素で印を付け (明るいテーマは黄色の上の暗い文字、`dark` クラスの下は暗い琥珀色の上の明るい文字。どちらも WCAG 2.2 AAA の 7:1 を超える)、`createExactMatchRanker(query, fields)` はいずれかのフィールドに一致を持つ結果を先頭へ移す (各グループ内ではあいまい検索の順序を保つ)。そのため、フィールドにハイライトが付くのは、そのフィールドがレコードを完全一致として並べさせるときちょうど。かなの読みに印が付くのはどのキーワードもローマ字として読めるときだけ。
|
|
314
439
|
|
|
315
440
|
入力されたままの検索語を使うのは、正規化が検索語の持つ表記を落とすことがあるため。全角/半角の統一 (Unicode の NFKC) は `㈱` を `(株)` と読むので、`㈱山田` は検索語 `(株)山田` になるが、ハイライトと並べ替えは `㈱` で保存された会社の `㈱山田` を探し続ける。検索のアウトレットコンテキストは両方を運ぶ: `searchQuery` (入力されたまま) と `searchTerm` (`normalizeSearchInput(searchQuery)`)。
|
|
316
441
|
|
|
@@ -339,7 +464,7 @@ Every string the client components render on their own (tabs, buttons, headings,
|
|
|
339
464
|
| `ContactMapAppView` | `workerUrls` | `ContactMapWorkerUrls` | Checked like `config.workerUrls`, then layered over the surrounding provider's key by key: a key left out or `undefined` keeps the provider's value (`layerContactMapWorkerUrls`). |
|
|
340
465
|
| `ContactMapAppView` | `title` | `string` | Per-instance heading; omitted ⇒ the `appTitle` label. |
|
|
341
466
|
| `ContactMapSearchPage` | `workerUrls` | `{ indexWorker?, levenshteinWorker? }` | Layered over the provider's like the view's; a `treeWorker` with a value throws a `RangeError` that says to set it on the provider or the view (`treeWorker: undefined` counts as left out). |
|
|
342
|
-
| `SwipeOverlay` | `title` | `string` | Per-instance dialog
|
|
467
|
+
| `SwipeOverlay` | `title` | `string` | Per-instance heading of the overlay, which also names its dialog; omitted ⇒ the `overlayTitle` label. |
|
|
343
468
|
|
|
344
469
|
Components rendered outside any provider use the `en` catalog. `useContactMapLabels()` returns the resolved labels of the nearest provider, for host chrome that should speak the same language (for example the component a custom `renderHeader` renders).
|
|
345
470
|
プロバイダー外で描画したコンポーネントは `en` カタログを使う。`useContactMapLabels()` は直近プロバイダーの解決済みラベルを返すフックで、同じ言語で表示したいホスト側のクローム (独自 `renderHeader` が描画するコンポーネントなど) 向け。
|
|
@@ -422,8 +547,6 @@ Function keys are shown with their arguments; the cells show sample output (`cou
|
|
|
422
547
|
| `scrollRight` | `"Scroll right"` | `"右へスクロール"` |
|
|
423
548
|
| `verticalScrollBar` | `"Vertical"` | `"縦方向"` |
|
|
424
549
|
| `horizontalScrollBar` | `"Horizontal"` | `"横方向"` |
|
|
425
|
-
| `verticalScrollThumb` | `"Vertical scroll position"` | `"縦スクロール位置"` |
|
|
426
|
-
| `horizontalScrollThumb` | `"Horizontal scroll position"` | `"横スクロール位置"` |
|
|
427
550
|
| `scrollToTop` | `"Top"` | `"先頭へ"` |
|
|
428
551
|
| `scrollToBottom` | `"Bottom"` | `"末尾へ"` |
|
|
429
552
|
| `noItems` | `"No items"` | `"項目がありません"` |
|
|
@@ -473,6 +596,8 @@ Function keys are shown with their arguments; the cells show sample output (`cou
|
|
|
473
596
|
| `listRowNumber(rowNumber)` | `"No. 3"` | `"No. 3"` |
|
|
474
597
|
| `listNoSearchResults` | `"No search results found"` | `"検索結果が見つかりません"` |
|
|
475
598
|
| `listNoData` | `"No data"` | `"データがありません"` |
|
|
599
|
+
| `listboxLabel` | `"Contact list"` | `"連絡先一覧"` |
|
|
600
|
+
| `listKeyboardHelp` | `"Up and down arrows move between contacts, Page Up and Page Down move by a screen, Home and End go to the first and the last; Enter or Space opens the contact's details."` | `"上下の矢印キーで連絡先を移り、Page Up と Page Down で 1 画面ずつ、Home と End で先頭と末尾へ移ります。Enter か Space で連絡先の詳細を開きます。"` |
|
|
476
601
|
| `listResizeHandle` | `"Resize the border between the contact list and the detail pane"` | `"連絡先一覧と詳細ペインの境界のサイズ変更ハンドル"` |
|
|
477
602
|
| `detailHeading` | `"Contact details"` | `"連絡先詳細"` |
|
|
478
603
|
| `close` | `"Close"` | `"閉じる"` |
|
|
@@ -546,7 +671,6 @@ Function keys are shown with their arguments; the cells show sample output (`cou
|
|
|
546
671
|
| `popupLastContactDate` | `"Last contact:"` | `"最終コンタクト日:"` |
|
|
547
672
|
| `popupNoContactMethods` | `"No contact information to display"` | `"表示できる連絡先情報がありません"` |
|
|
548
673
|
| `overlayTitle` | `"Details"` | `"詳細"` |
|
|
549
|
-
| `overlayBackdrop` | `"Tap the background to close"` | `"背景をタップして閉じる"` |
|
|
550
674
|
| `settingsResetAllTitle` | `"Reset all settings"` | `"すべての設定をリセット"` |
|
|
551
675
|
| `settingsResetAll` | `"Reset all"` | `"すべてリセット"` |
|
|
552
676
|
| `settingsTabsLabel` | `"Search option tabs"` | `"検索オプション設定タブ"` |
|
|
@@ -648,6 +772,7 @@ Function keys are shown with their arguments; the cells show sample output (`cou
|
|
|
648
772
|
| `statsRebuilding` | `"Rebuilding..."` | `"再構築中..."` |
|
|
649
773
|
| `statsRebuild` | `"Rebuild Index"` | `"インデックス再構築"` |
|
|
650
774
|
| `statsResetTitle` | `"Reset statistics"` | `"統計をリセット"` |
|
|
775
|
+
| `statsTabsLabel` | `"Statistics tabs"` | `"検索統計タブ"` |
|
|
651
776
|
| `statsOverviewTab` | `"Overview"` | `"概要"` |
|
|
652
777
|
| `statsIndexTab` | `"Index"` | `"Index"` |
|
|
653
778
|
| `statsLevenshteinTab` | `"Levenshtein"` | `"Levenshtein"` |
|
package/dist/client.d.mts
CHANGED
|
@@ -24,17 +24,6 @@ interface BasicSearchSettingsProps {
|
|
|
24
24
|
setOpenEmailsWithGmail: React.Dispatch<React.SetStateAction<boolean>>;
|
|
25
25
|
}
|
|
26
26
|
declare const BasicSearchSettings: react.NamedExoticComponent<BasicSearchSettingsProps>;
|
|
27
|
-
type PopupCloseOptions = {
|
|
28
|
-
suppressLongPress?: boolean;
|
|
29
|
-
cancelLongPressTimer?: boolean;
|
|
30
|
-
};
|
|
31
|
-
type ContactDetailPopupProps = {
|
|
32
|
-
contactData: ContactRecord;
|
|
33
|
-
openEmailsWithGmail: boolean;
|
|
34
|
-
openGmailCompose: (email: string) => void;
|
|
35
|
-
onRequestClose: (options?: PopupCloseOptions) => void;
|
|
36
|
-
};
|
|
37
|
-
declare const ContactDetailPopup: ({ contactData, openEmailsWithGmail, openGmailCompose, onRequestClose }: ContactDetailPopupProps) => react.ReactPortal | null;
|
|
38
27
|
interface ContactDetailGridProps {
|
|
39
28
|
contactData: ContactRecord;
|
|
40
29
|
searchTerm: string;
|
|
@@ -42,17 +31,26 @@ interface ContactDetailGridProps {
|
|
|
42
31
|
openEmailsWithGmail: boolean;
|
|
43
32
|
openGmailCompose: (email: string) => void;
|
|
44
33
|
isPopupVisible: boolean;
|
|
45
|
-
onRequestClose: (
|
|
34
|
+
onRequestClose: () => void;
|
|
46
35
|
}
|
|
47
36
|
declare const ContactDetailGrid: ({ contactData, searchTerm, enableHighlighting, openEmailsWithGmail, openGmailCompose, isPopupVisible, onRequestClose }: ContactDetailGridProps) => react.JSX.Element;
|
|
37
|
+
type ContactDetailPanelPlacement = "overlay" | "pane";
|
|
48
38
|
type ContactDetailPanelProps = {
|
|
49
39
|
contact: ContactRecord | null;
|
|
40
|
+
placement: ContactDetailPanelPlacement;
|
|
50
41
|
searchTerm?: string;
|
|
51
42
|
enableHighlighting?: boolean;
|
|
52
43
|
style?: CSSProperties;
|
|
53
44
|
className?: string;
|
|
54
45
|
};
|
|
55
|
-
declare const ContactDetailPanel: ({ contact, searchTerm, enableHighlighting, style, className }: ContactDetailPanelProps) => react.JSX.Element;
|
|
46
|
+
declare const ContactDetailPanel: ({ contact, placement, searchTerm, enableHighlighting, style, className }: ContactDetailPanelProps) => react.JSX.Element;
|
|
47
|
+
type ContactDetailPopupProps = {
|
|
48
|
+
contactData: ContactRecord;
|
|
49
|
+
openEmailsWithGmail: boolean;
|
|
50
|
+
openGmailCompose: (email: string) => void;
|
|
51
|
+
onRequestClose: () => void;
|
|
52
|
+
};
|
|
53
|
+
declare const ContactDetailPopup: ({ contactData, openEmailsWithGmail, openGmailCompose, onRequestClose }: ContactDetailPopupProps) => react.ReactPortal;
|
|
56
54
|
interface ContactDetailRowLayoutProps {
|
|
57
55
|
fullName: ReactNode;
|
|
58
56
|
title?: ReactNode;
|
|
@@ -132,6 +130,8 @@ type ContactMapOwnLabels = {
|
|
|
132
130
|
readonly listRowNumber: (rowNumber: number) => string;
|
|
133
131
|
readonly listNoSearchResults: string;
|
|
134
132
|
readonly listNoData: string;
|
|
133
|
+
readonly listboxLabel: string;
|
|
134
|
+
readonly listKeyboardHelp: string;
|
|
135
135
|
readonly listResizeHandle: string;
|
|
136
136
|
readonly detailHeading: string;
|
|
137
137
|
readonly close: string;
|
|
@@ -205,7 +205,6 @@ type ContactMapOwnLabels = {
|
|
|
205
205
|
readonly popupLastContactDate: string;
|
|
206
206
|
readonly popupNoContactMethods: string;
|
|
207
207
|
readonly overlayTitle: string;
|
|
208
|
-
readonly overlayBackdrop: string;
|
|
209
208
|
readonly settingsResetAllTitle: string;
|
|
210
209
|
readonly settingsResetAll: string;
|
|
211
210
|
readonly settingsTabsLabel: string;
|
|
@@ -307,6 +306,7 @@ type ContactMapOwnLabels = {
|
|
|
307
306
|
readonly statsRebuilding: string;
|
|
308
307
|
readonly statsRebuild: string;
|
|
309
308
|
readonly statsResetTitle: string;
|
|
309
|
+
readonly statsTabsLabel: string;
|
|
310
310
|
readonly statsOverviewTab: string;
|
|
311
311
|
readonly statsIndexTab: string;
|
|
312
312
|
readonly statsLevenshteinTab: string;
|
|
@@ -462,10 +462,10 @@ declare const composeTreeVirtualScrollOptions: <T extends DirectoryTreeVirtualSc
|
|
|
462
462
|
viewportHeightOverride: number;
|
|
463
463
|
behaviorOptions: {
|
|
464
464
|
enablePointerDrag: boolean;
|
|
465
|
+
overscrollBehavior?: _aiquants_virtualscroll.ScrollPaneProps["overscrollBehavior"];
|
|
465
466
|
pointerDragInputs?: _aiquants_virtualscroll.ScrollPaneProps["pointerDragInputs"];
|
|
466
467
|
wheelSpeedMultiplier?: number;
|
|
467
468
|
inertiaOptions?: _aiquants_virtualscroll.ScrollPaneProps["inertiaOptions"];
|
|
468
|
-
overscrollBehavior?: _aiquants_virtualscroll.ScrollPaneProps["overscrollBehavior"];
|
|
469
469
|
clipItemHeight?: boolean;
|
|
470
470
|
resetOnGetItemHeightChange?: boolean;
|
|
471
471
|
};
|
|
@@ -644,7 +644,7 @@ type UseLongPressPopupOptions<T> = {
|
|
|
644
644
|
interface UseLongPressPopupReturn<T> {
|
|
645
645
|
isPopupVisible: boolean;
|
|
646
646
|
popupItem: T | null;
|
|
647
|
-
handleClosePopup: (
|
|
647
|
+
handleClosePopup: () => void;
|
|
648
648
|
}
|
|
649
649
|
declare const useLongPressPopup: <T>({ ref, onSelect, resolveItem, item }: UseLongPressPopupOptions<T>) => UseLongPressPopupReturn<T>;
|
|
650
650
|
interface UseResponsiveTwoColumnLayoutOptions {
|
|
@@ -729,4 +729,4 @@ declare const Tabs: react.ForwardRefExoticComponent<TabsPrimitive.TabsProps & re
|
|
|
729
729
|
declare const TabsList: react.ForwardRefExoticComponent<Omit<TabsPrimitive.TabsListProps & react.RefAttributes<HTMLDivElement>, "ref"> & react.RefAttributes<HTMLDivElement>>;
|
|
730
730
|
declare const TabsTrigger: react.ForwardRefExoticComponent<Omit<TabsPrimitive.TabsTriggerProps & react.RefAttributes<HTMLButtonElement>, "ref"> & react.RefAttributes<HTMLButtonElement>>;
|
|
731
731
|
declare const TabsContent: react.ForwardRefExoticComponent<Omit<TabsPrimitive.TabsContentProps & react.RefAttributes<HTMLDivElement>, "ref"> & react.RefAttributes<HTMLDivElement>>;
|
|
732
|
-
export { AdvancedSearchSettings, type AdvancedSearchSettingsProps, BasicSearchSettings, type BasicSearchSettingsProps, CONTACT_MAP_LABEL_CATALOGS, CONTACT_MAP_LABEL_KEYS, ContactDetailGrid, type ContactDetailGridProps, type ContactDetailGridSkeletonProps, ContactDetailPanel, type ContactDetailPanelProps, ContactDetailPopup, type ContactDetailPopupProps, ContactDetailRowLayout, type ContactDetailRowLayoutProps, ContactMapAnnotation, type ContactMapAnnotationProps, ContactMapAppView, type ContactMapAppViewProps, type ContactMapChromeSurface, type ContactMapConfig, ContactMapConfigProvider, type ContactMapHistoryEntry, type ContactMapLabelOverrides, type ContactMapLabels, type ContactMapLocale, type ContactMapOwnLabels, type ContactMapQueryLengthStat, ContactMapSearchListView, ContactMapSearchPage, type ContactMapSearchPageProps, ContactMapSearchTabGroup, type ContactMapSearchTabGroupProps, ContactMapSearchTreeView, type ContactMapSearchTreeViewProps, ContactMapStreamClient, type ContactMapStreamClientDeps, type ContactMapStreamHandle, ContactMapStreamPhase, type ContactMapStreamProgress, type ContactMapStreamState, type ContactMapTab, type ContactMapWorkerUrlKey, type ContactMapWorkerUrls, type ContactMapWorkerUrlsSurface, HighlightedText, type HighlightedTextProps, type HorizontalDragScrollHandlers, IndexWorkerSettings, type IndexWorkerSettingsProps, LIST_COLLAPSE_THRESHOLD, LIST_DETAIL_PANEL_MIN_WIDTH, LIST_EXPAND_THRESHOLD, LIST_PANEL_MIN_WIDTH, LIST_RESIZE_HANDLE_THICKNESS, LevenshteinWorkerSettings, type LevenshteinWorkerSettingsProps,
|
|
732
|
+
export { AdvancedSearchSettings, type AdvancedSearchSettingsProps, BasicSearchSettings, type BasicSearchSettingsProps, CONTACT_MAP_LABEL_CATALOGS, CONTACT_MAP_LABEL_KEYS, ContactDetailGrid, type ContactDetailGridProps, type ContactDetailGridSkeletonProps, ContactDetailPanel, type ContactDetailPanelPlacement, type ContactDetailPanelProps, ContactDetailPopup, type ContactDetailPopupProps, ContactDetailRowLayout, type ContactDetailRowLayoutProps, ContactMapAnnotation, type ContactMapAnnotationProps, ContactMapAppView, type ContactMapAppViewProps, type ContactMapChromeSurface, type ContactMapConfig, ContactMapConfigProvider, type ContactMapHistoryEntry, type ContactMapLabelOverrides, type ContactMapLabels, type ContactMapLocale, type ContactMapOwnLabels, type ContactMapQueryLengthStat, ContactMapSearchListView, ContactMapSearchPage, type ContactMapSearchPageProps, ContactMapSearchTabGroup, type ContactMapSearchTabGroupProps, ContactMapSearchTreeView, type ContactMapSearchTreeViewProps, ContactMapStreamClient, type ContactMapStreamClientDeps, type ContactMapStreamHandle, ContactMapStreamPhase, type ContactMapStreamProgress, type ContactMapStreamState, type ContactMapTab, type ContactMapWorkerUrlKey, type ContactMapWorkerUrls, type ContactMapWorkerUrlsSurface, HighlightedText, type HighlightedTextProps, type HorizontalDragScrollHandlers, IndexWorkerSettings, type IndexWorkerSettingsProps, LIST_COLLAPSE_THRESHOLD, LIST_DETAIL_PANEL_MIN_WIDTH, LIST_EXPAND_THRESHOLD, LIST_PANEL_MIN_WIDTH, LIST_RESIZE_HANDLE_THICKNESS, LevenshteinWorkerSettings, type LevenshteinWorkerSettingsProps, Progress, type ProgressProps, SearchOptionsPanel, type SearchOptionsPanelProps, type SearchOptionsPanelTab, StatItem, type StatItemProps, StatisticsPanel, type StatisticsPanelProps, type StatisticsPanelTab, SwipeOverlay, type SwipeOverlayProps, TREE_COLLAPSE_THRESHOLD, TREE_DETAIL_PANEL_MIN_WIDTH, TREE_EXPAND_THRESHOLD, TREE_PANEL_MIN_WIDTH, TREE_RESIZE_HANDLE_THICKNESS, Tabs, TabsContent, TabsList, TabsTrigger, TreeWorkerSession, type TreeWorkerSessionOptions, type TreeWorkerSnapshot, type TreeWorkerSource, type TreeWorkerState, type UseDynamicViewportHeightOptions, type UseDynamicViewportHeightResult, type UseHorizontalDragScrollOptions, type UseLongPressPopupOptions, type UseLongPressPopupReturn, type UseResponsiveTwoColumnLayoutOptions, type UseResponsiveTwoColumnLayoutResult, type WorkerStatsKind, WorkerStatsSection, type WorkerStatsSectionProps, assertContactMapStreamEndpoint, assertContactMapTreeWorkerUrl, assertContactMapWorkerUrls, composeTreeVirtualScrollOptions, contactMapShouldRevalidate, countContactMapCompanies, deserializeStreamRecord, getContactMapStreamClient, getTreeWorkerSession, layerContactMapWorkerUrls, resetContactMapStreamClientForTesting, resetTreeWorkerSessionForTesting, resolveContactMapLabels, useAnimatedNumber, useContactMapConfig, useContactMapLabels, useContactMapStream, useContactPanelSizing, useDynamicViewportHeight, useHorizontalDragScroll, useLongPressPopup, useReportPopupVisibility, useResponsiveTwoColumnLayout, useRowPopupRegistry, useStreamedContactMapContext, useTreeWorker };
|
package/dist/client.d.ts
CHANGED
|
@@ -24,17 +24,6 @@ interface BasicSearchSettingsProps {
|
|
|
24
24
|
setOpenEmailsWithGmail: React.Dispatch<React.SetStateAction<boolean>>;
|
|
25
25
|
}
|
|
26
26
|
declare const BasicSearchSettings: react.NamedExoticComponent<BasicSearchSettingsProps>;
|
|
27
|
-
type PopupCloseOptions = {
|
|
28
|
-
suppressLongPress?: boolean;
|
|
29
|
-
cancelLongPressTimer?: boolean;
|
|
30
|
-
};
|
|
31
|
-
type ContactDetailPopupProps = {
|
|
32
|
-
contactData: ContactRecord;
|
|
33
|
-
openEmailsWithGmail: boolean;
|
|
34
|
-
openGmailCompose: (email: string) => void;
|
|
35
|
-
onRequestClose: (options?: PopupCloseOptions) => void;
|
|
36
|
-
};
|
|
37
|
-
declare const ContactDetailPopup: ({ contactData, openEmailsWithGmail, openGmailCompose, onRequestClose }: ContactDetailPopupProps) => react.ReactPortal | null;
|
|
38
27
|
interface ContactDetailGridProps {
|
|
39
28
|
contactData: ContactRecord;
|
|
40
29
|
searchTerm: string;
|
|
@@ -42,17 +31,26 @@ interface ContactDetailGridProps {
|
|
|
42
31
|
openEmailsWithGmail: boolean;
|
|
43
32
|
openGmailCompose: (email: string) => void;
|
|
44
33
|
isPopupVisible: boolean;
|
|
45
|
-
onRequestClose: (
|
|
34
|
+
onRequestClose: () => void;
|
|
46
35
|
}
|
|
47
36
|
declare const ContactDetailGrid: ({ contactData, searchTerm, enableHighlighting, openEmailsWithGmail, openGmailCompose, isPopupVisible, onRequestClose }: ContactDetailGridProps) => react.JSX.Element;
|
|
37
|
+
type ContactDetailPanelPlacement = "overlay" | "pane";
|
|
48
38
|
type ContactDetailPanelProps = {
|
|
49
39
|
contact: ContactRecord | null;
|
|
40
|
+
placement: ContactDetailPanelPlacement;
|
|
50
41
|
searchTerm?: string;
|
|
51
42
|
enableHighlighting?: boolean;
|
|
52
43
|
style?: CSSProperties;
|
|
53
44
|
className?: string;
|
|
54
45
|
};
|
|
55
|
-
declare const ContactDetailPanel: ({ contact, searchTerm, enableHighlighting, style, className }: ContactDetailPanelProps) => react.JSX.Element;
|
|
46
|
+
declare const ContactDetailPanel: ({ contact, placement, searchTerm, enableHighlighting, style, className }: ContactDetailPanelProps) => react.JSX.Element;
|
|
47
|
+
type ContactDetailPopupProps = {
|
|
48
|
+
contactData: ContactRecord;
|
|
49
|
+
openEmailsWithGmail: boolean;
|
|
50
|
+
openGmailCompose: (email: string) => void;
|
|
51
|
+
onRequestClose: () => void;
|
|
52
|
+
};
|
|
53
|
+
declare const ContactDetailPopup: ({ contactData, openEmailsWithGmail, openGmailCompose, onRequestClose }: ContactDetailPopupProps) => react.ReactPortal;
|
|
56
54
|
interface ContactDetailRowLayoutProps {
|
|
57
55
|
fullName: ReactNode;
|
|
58
56
|
title?: ReactNode;
|
|
@@ -132,6 +130,8 @@ type ContactMapOwnLabels = {
|
|
|
132
130
|
readonly listRowNumber: (rowNumber: number) => string;
|
|
133
131
|
readonly listNoSearchResults: string;
|
|
134
132
|
readonly listNoData: string;
|
|
133
|
+
readonly listboxLabel: string;
|
|
134
|
+
readonly listKeyboardHelp: string;
|
|
135
135
|
readonly listResizeHandle: string;
|
|
136
136
|
readonly detailHeading: string;
|
|
137
137
|
readonly close: string;
|
|
@@ -205,7 +205,6 @@ type ContactMapOwnLabels = {
|
|
|
205
205
|
readonly popupLastContactDate: string;
|
|
206
206
|
readonly popupNoContactMethods: string;
|
|
207
207
|
readonly overlayTitle: string;
|
|
208
|
-
readonly overlayBackdrop: string;
|
|
209
208
|
readonly settingsResetAllTitle: string;
|
|
210
209
|
readonly settingsResetAll: string;
|
|
211
210
|
readonly settingsTabsLabel: string;
|
|
@@ -307,6 +306,7 @@ type ContactMapOwnLabels = {
|
|
|
307
306
|
readonly statsRebuilding: string;
|
|
308
307
|
readonly statsRebuild: string;
|
|
309
308
|
readonly statsResetTitle: string;
|
|
309
|
+
readonly statsTabsLabel: string;
|
|
310
310
|
readonly statsOverviewTab: string;
|
|
311
311
|
readonly statsIndexTab: string;
|
|
312
312
|
readonly statsLevenshteinTab: string;
|
|
@@ -462,10 +462,10 @@ declare const composeTreeVirtualScrollOptions: <T extends DirectoryTreeVirtualSc
|
|
|
462
462
|
viewportHeightOverride: number;
|
|
463
463
|
behaviorOptions: {
|
|
464
464
|
enablePointerDrag: boolean;
|
|
465
|
+
overscrollBehavior?: _aiquants_virtualscroll.ScrollPaneProps["overscrollBehavior"];
|
|
465
466
|
pointerDragInputs?: _aiquants_virtualscroll.ScrollPaneProps["pointerDragInputs"];
|
|
466
467
|
wheelSpeedMultiplier?: number;
|
|
467
468
|
inertiaOptions?: _aiquants_virtualscroll.ScrollPaneProps["inertiaOptions"];
|
|
468
|
-
overscrollBehavior?: _aiquants_virtualscroll.ScrollPaneProps["overscrollBehavior"];
|
|
469
469
|
clipItemHeight?: boolean;
|
|
470
470
|
resetOnGetItemHeightChange?: boolean;
|
|
471
471
|
};
|
|
@@ -644,7 +644,7 @@ type UseLongPressPopupOptions<T> = {
|
|
|
644
644
|
interface UseLongPressPopupReturn<T> {
|
|
645
645
|
isPopupVisible: boolean;
|
|
646
646
|
popupItem: T | null;
|
|
647
|
-
handleClosePopup: (
|
|
647
|
+
handleClosePopup: () => void;
|
|
648
648
|
}
|
|
649
649
|
declare const useLongPressPopup: <T>({ ref, onSelect, resolveItem, item }: UseLongPressPopupOptions<T>) => UseLongPressPopupReturn<T>;
|
|
650
650
|
interface UseResponsiveTwoColumnLayoutOptions {
|
|
@@ -729,4 +729,4 @@ declare const Tabs: react.ForwardRefExoticComponent<TabsPrimitive.TabsProps & re
|
|
|
729
729
|
declare const TabsList: react.ForwardRefExoticComponent<Omit<TabsPrimitive.TabsListProps & react.RefAttributes<HTMLDivElement>, "ref"> & react.RefAttributes<HTMLDivElement>>;
|
|
730
730
|
declare const TabsTrigger: react.ForwardRefExoticComponent<Omit<TabsPrimitive.TabsTriggerProps & react.RefAttributes<HTMLButtonElement>, "ref"> & react.RefAttributes<HTMLButtonElement>>;
|
|
731
731
|
declare const TabsContent: react.ForwardRefExoticComponent<Omit<TabsPrimitive.TabsContentProps & react.RefAttributes<HTMLDivElement>, "ref"> & react.RefAttributes<HTMLDivElement>>;
|
|
732
|
-
export { AdvancedSearchSettings, type AdvancedSearchSettingsProps, BasicSearchSettings, type BasicSearchSettingsProps, CONTACT_MAP_LABEL_CATALOGS, CONTACT_MAP_LABEL_KEYS, ContactDetailGrid, type ContactDetailGridProps, type ContactDetailGridSkeletonProps, ContactDetailPanel, type ContactDetailPanelProps, ContactDetailPopup, type ContactDetailPopupProps, ContactDetailRowLayout, type ContactDetailRowLayoutProps, ContactMapAnnotation, type ContactMapAnnotationProps, ContactMapAppView, type ContactMapAppViewProps, type ContactMapChromeSurface, type ContactMapConfig, ContactMapConfigProvider, type ContactMapHistoryEntry, type ContactMapLabelOverrides, type ContactMapLabels, type ContactMapLocale, type ContactMapOwnLabels, type ContactMapQueryLengthStat, ContactMapSearchListView, ContactMapSearchPage, type ContactMapSearchPageProps, ContactMapSearchTabGroup, type ContactMapSearchTabGroupProps, ContactMapSearchTreeView, type ContactMapSearchTreeViewProps, ContactMapStreamClient, type ContactMapStreamClientDeps, type ContactMapStreamHandle, ContactMapStreamPhase, type ContactMapStreamProgress, type ContactMapStreamState, type ContactMapTab, type ContactMapWorkerUrlKey, type ContactMapWorkerUrls, type ContactMapWorkerUrlsSurface, HighlightedText, type HighlightedTextProps, type HorizontalDragScrollHandlers, IndexWorkerSettings, type IndexWorkerSettingsProps, LIST_COLLAPSE_THRESHOLD, LIST_DETAIL_PANEL_MIN_WIDTH, LIST_EXPAND_THRESHOLD, LIST_PANEL_MIN_WIDTH, LIST_RESIZE_HANDLE_THICKNESS, LevenshteinWorkerSettings, type LevenshteinWorkerSettingsProps,
|
|
732
|
+
export { AdvancedSearchSettings, type AdvancedSearchSettingsProps, BasicSearchSettings, type BasicSearchSettingsProps, CONTACT_MAP_LABEL_CATALOGS, CONTACT_MAP_LABEL_KEYS, ContactDetailGrid, type ContactDetailGridProps, type ContactDetailGridSkeletonProps, ContactDetailPanel, type ContactDetailPanelPlacement, type ContactDetailPanelProps, ContactDetailPopup, type ContactDetailPopupProps, ContactDetailRowLayout, type ContactDetailRowLayoutProps, ContactMapAnnotation, type ContactMapAnnotationProps, ContactMapAppView, type ContactMapAppViewProps, type ContactMapChromeSurface, type ContactMapConfig, ContactMapConfigProvider, type ContactMapHistoryEntry, type ContactMapLabelOverrides, type ContactMapLabels, type ContactMapLocale, type ContactMapOwnLabels, type ContactMapQueryLengthStat, ContactMapSearchListView, ContactMapSearchPage, type ContactMapSearchPageProps, ContactMapSearchTabGroup, type ContactMapSearchTabGroupProps, ContactMapSearchTreeView, type ContactMapSearchTreeViewProps, ContactMapStreamClient, type ContactMapStreamClientDeps, type ContactMapStreamHandle, ContactMapStreamPhase, type ContactMapStreamProgress, type ContactMapStreamState, type ContactMapTab, type ContactMapWorkerUrlKey, type ContactMapWorkerUrls, type ContactMapWorkerUrlsSurface, HighlightedText, type HighlightedTextProps, type HorizontalDragScrollHandlers, IndexWorkerSettings, type IndexWorkerSettingsProps, LIST_COLLAPSE_THRESHOLD, LIST_DETAIL_PANEL_MIN_WIDTH, LIST_EXPAND_THRESHOLD, LIST_PANEL_MIN_WIDTH, LIST_RESIZE_HANDLE_THICKNESS, LevenshteinWorkerSettings, type LevenshteinWorkerSettingsProps, Progress, type ProgressProps, SearchOptionsPanel, type SearchOptionsPanelProps, type SearchOptionsPanelTab, StatItem, type StatItemProps, StatisticsPanel, type StatisticsPanelProps, type StatisticsPanelTab, SwipeOverlay, type SwipeOverlayProps, TREE_COLLAPSE_THRESHOLD, TREE_DETAIL_PANEL_MIN_WIDTH, TREE_EXPAND_THRESHOLD, TREE_PANEL_MIN_WIDTH, TREE_RESIZE_HANDLE_THICKNESS, Tabs, TabsContent, TabsList, TabsTrigger, TreeWorkerSession, type TreeWorkerSessionOptions, type TreeWorkerSnapshot, type TreeWorkerSource, type TreeWorkerState, type UseDynamicViewportHeightOptions, type UseDynamicViewportHeightResult, type UseHorizontalDragScrollOptions, type UseLongPressPopupOptions, type UseLongPressPopupReturn, type UseResponsiveTwoColumnLayoutOptions, type UseResponsiveTwoColumnLayoutResult, type WorkerStatsKind, WorkerStatsSection, type WorkerStatsSectionProps, assertContactMapStreamEndpoint, assertContactMapTreeWorkerUrl, assertContactMapWorkerUrls, composeTreeVirtualScrollOptions, contactMapShouldRevalidate, countContactMapCompanies, deserializeStreamRecord, getContactMapStreamClient, getTreeWorkerSession, layerContactMapWorkerUrls, resetContactMapStreamClientForTesting, resetTreeWorkerSessionForTesting, resolveContactMapLabels, useAnimatedNumber, useContactMapConfig, useContactMapLabels, useContactMapStream, useContactPanelSizing, useDynamicViewportHeight, useHorizontalDragScroll, useLongPressPopup, useReportPopupVisibility, useResponsiveTwoColumnLayout, useRowPopupRegistry, useStreamedContactMapContext, useTreeWorker };
|