@nteract/sift 0.0.1 → 0.5.5-nightly.38500811922

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.
Files changed (32) hide show
  1. package/README.md +100 -7
  2. package/docs/embedding-guide.md +185 -0
  3. package/lib/LICENSE +28 -0
  4. package/lib/THIRD_PARTY_NOTICES.md +3079 -0
  5. package/lib/handoff.css +37 -0
  6. package/lib/handoff.js +26 -0
  7. package/lib/index.js +3455 -0
  8. package/lib/style.css +2 -0
  9. package/lib/types/packages/sift/src/auto-width.d.ts +13 -0
  10. package/lib/types/packages/sift/src/column-menu.d.ts +8 -0
  11. package/lib/types/packages/sift/src/components/column-context-menu.d.ts +32 -0
  12. package/lib/types/packages/sift/src/components/image-viewer.d.ts +16 -0
  13. package/lib/types/packages/sift/src/events.d.ts +1 -0
  14. package/lib/types/packages/sift/src/file-data.d.ts +36 -0
  15. package/lib/types/packages/sift/src/filter-schema.d.ts +100 -0
  16. package/lib/types/packages/sift/src/handoff.d.ts +11 -0
  17. package/lib/types/packages/sift/src/index.d.ts +28 -0
  18. package/lib/types/packages/sift/src/parquet-features.d.ts +15 -0
  19. package/lib/types/packages/sift/src/predicate.d.ts +199 -0
  20. package/lib/types/packages/sift/src/react.d.ts +97 -0
  21. package/lib/types/packages/sift/src/sparkline.d.ts +25 -0
  22. package/lib/types/packages/sift/src/table-response.d.ts +5 -0
  23. package/lib/types/packages/sift/src/table.d.ts +175 -0
  24. package/lib/types/packages/sift/src/wasm-summaries.d.ts +3 -0
  25. package/lib/types/packages/sift/src/wasm-table-data.d.ts +19 -0
  26. package/lib/types/src/components/ui/button.d.ts +11 -0
  27. package/lib/types/src/components/ui/popover.d.ts +7 -0
  28. package/lib/types/src/lib/utils.d.ts +2 -0
  29. package/lib/wasm/sift_wasm.d.ts +382 -0
  30. package/lib/wasm/sift_wasm.js +1398 -0
  31. package/lib/wasm/sift_wasm_bg.wasm +0 -0
  32. package/package.json +73 -5
package/README.md CHANGED
@@ -1,13 +1,106 @@
1
- # @nteract/sift 0.0.1
1
+ # Sift
2
2
 
3
- This version only reserves the package name so nteract's release workflow can
4
- publish through npm trusted publishing. It contains no code.
3
+ Crossfilter data explorer. [Pretext](https://github.com/chenglou/pretext) × [Arrow](https://arrow.apache.org/).
5
4
 
6
- Install a real build instead:
5
+ ![Sift — crossfilter in action](https://img.runt.run/sift/crossfilter-demo.gif)
6
+
7
+ Published as [`@nteract/sift`](https://www.npmjs.com/package/@nteract/sift). Try it at [rgbkrk.github.io/sift](https://rgbkrk.github.io/sift/).
8
+
9
+ ## Features
10
+
11
+ - **Local CSV/TSV, Parquet, and Arrow IPC streams** — bounded file adapters, no notebook or server needed
12
+ - **Stream hosted Arrow IPC or load Parquet URLs** — WASM-native
13
+ - **Crossfilter** — brush histograms to filter, all other summaries update instantly
14
+ - **Column profiling** — null%, distinct count shown inline in headers
15
+ - **Smart summaries** — histograms, category bars, boolean ratios, binary value bars, searchable popovers. Adapts visualization to column type × cardinality.
16
+ - **Column type casting** — right-click to treat text as numbers, dates, booleans — with full undo
17
+ - **Smart column detection** — pandas index columns, HuggingFace ClassLabel features
18
+ - **Virtual scroll** — 100k+ rows at 120fps. Pretext layout at 0.0002ms/cell.
19
+ - **Odometer status bar** — rolling digit animation for row count, visible range, FPS
20
+ - **Multi-instance** — embed multiple tables on one page (notebook demo included)
21
+ - **RxJS streaming** — cancellable dataset loading via `switchMap`
22
+ - **Mobile** — tap any row for a detail sheet with all column values
23
+ - **Dark mode**, keyboard nav, pinned columns, ARIA grid
24
+ - **8 HuggingFace datasets** built into the demo
25
+
26
+ ## Quick start
27
+
28
+ From the nteract repository root:
29
+
30
+ ```sh
31
+ pnpm install --frozen-lockfile
32
+ cargo xtask wasm sift --skip-renderer-plugins
33
+ pnpm --dir packages/sift dev
34
+ ```
35
+
36
+ ## Use as a library
37
+
38
+ The package ships JavaScript, compiled CSS, TypeScript declarations, and WASM,
39
+ with notices for the Rust crates compiled into the WASM in
40
+ `lib/THIRD_PARTY_NOTICES.md`. React and React DOM are peer dependencies; no
41
+ notebook, kernel, or daemon is needed. Tested with React 19. Types resolve
42
+ under TypeScript's `bundler` module resolution (Vite, webpack, esbuild).
43
+
44
+ ```tsx
45
+ import { loadTableFile, SiftTable } from '@nteract/sift'
46
+ import '@nteract/sift/style.css'
47
+
48
+ const load = useCallback(() => loadTableFile(bytes), [bytes]) // Parquet or Arrow IPC
49
+ <SiftTable source={{ kind: 'loader', load }} style={{ height: 600 }} />
50
+ ```
51
+
52
+ Files load whole or fail; defaults are 16 MiB, 100,000 rows, and 256 columns.
53
+ CSV and TSV go through [`@nteract/sift-csv`](../sift-csv), a separate WASM
54
+ module that returns Arrow IPC bytes for `loadTableFile`, so apps that only open
55
+ Parquet or Arrow do not carry the CSV parser.
56
+
57
+ See the [embedding guide](docs/embedding-guide.md) for WASM asset setup, memory
58
+ limits, lifecycle, styling, and host viewer/editor integration.
59
+
60
+ ## Engine API
61
+
62
+ ```ts
63
+ engine.setSort('age', 'desc')
64
+ engine.setFilter(colIndex, { kind: 'range', min: 18, max: 65 })
65
+ engine.clearAllFilters()
66
+
67
+ // Inspect the current sort, filters, and counts.
68
+ const state = engine.getState()
69
+ ```
70
+
71
+ See [`docs/embedding-guide.md`](docs/embedding-guide.md) for the full API.
72
+
73
+ ## WASM compute (`sift-wasm`)
74
+
75
+ Rust crate wrapping arrow-rs. Parquet decoding, sort, histograms, value counts, string search, column casting — all in one WASM binary. Data lives in WASM memory; JS holds handles.
7
76
 
8
77
  ```sh
9
- npm install --save-exact @nteract/sift@nightly
78
+ cargo xtask wasm sift --skip-renderer-plugins
10
79
  ```
11
80
 
12
- Stable versions publish to `latest` from the nteract release workflow. See
13
- https://github.com/nteract/nteract/tree/main/packages/sift.
81
+ ## Stack
82
+
83
+ | Layer | What |
84
+ |-------|------|
85
+ | Layout | [@chenglou/pretext](https://github.com/chenglou/pretext) — DOM-free text measurement |
86
+ | Data | [Apache Arrow](https://arrow.apache.org/) — columnar, streamed via RecordBatchReader |
87
+ | Compute | [sift-wasm](../../crates/sift-wasm/) — arrow-rs WASM kernels |
88
+ | Reactivity | [RxJS](https://rxjs.dev/) — streaming pipeline |
89
+ | Charts | SVG histograms + HTML bars |
90
+
91
+ ## Development
92
+
93
+ Run from the repository root after the setup above:
94
+
95
+ ```sh
96
+ pnpm --dir packages/sift test # Vitest unit tests
97
+ pnpm --dir packages/sift test:e2e # Playwright E2E
98
+ pnpm --dir packages/sift build # production build (demo)
99
+ pnpm --dir packages/sift build:lib # lib/ (JS, CSS, types, WASM)
100
+ pnpm --dir packages/sift test:package # packed consumer outside the workspace
101
+ ```
102
+
103
+ ## Demo pages
104
+
105
+ - `/` — main demo with dataset picker
106
+ - `/notebook.html` — multi-table notebook simulation
@@ -0,0 +1,185 @@
1
+ # Embedding Sift
2
+
3
+ `@nteract/sift` is a browser table viewer with compiled JavaScript, CSS, TypeScript
4
+ interfaces, and a matching WebAssembly decoder. It does not require a notebook,
5
+ kernel, daemon, Tauri, Electron, or an nteract runtime connection. React and React
6
+ DOM are required even for the imperative API because column controls use React.
7
+
8
+ ## Install and assets
9
+
10
+ ```sh
11
+ npm install @nteract/sift react react-dom
12
+ ```
13
+
14
+ ```tsx
15
+ import { SiftTable, setWasmUrl } from '@nteract/sift'
16
+ import '@nteract/sift/style.css'
17
+ // Vite example: emit the packaged binary through the host's asset pipeline.
18
+ import wasmUrl from '@nteract/sift/sift.wasm?url'
19
+
20
+ setWasmUrl(wasmUrl) // Configure once, before the first binary table loads.
21
+ ```
22
+
23
+ Other bundlers can copy `@nteract/sift/sift.wasm` into their local assets and pass
24
+ its served URL to `setWasmUrl`. Without an override, the shipped wasm-bindgen glue
25
+ resolves `sift_wasm_bg.wasm` relative to itself; preserve that layout when serving
26
+ unbundled modules. Serve the binary with `application/wasm`. Keep the JavaScript
27
+ and WASM from the same package version. No CDN or data upload is required.
28
+
29
+ The host owns file access and its existing sandbox/CSP policy. In an Electron
30
+ app, read selected files through the approved main/preload bridge and pass text
31
+ or bytes to the renderer; Sift does not need Node integration or filesystem
32
+ access. The package's URL API explicitly fetches URLs supplied by the host.
33
+
34
+ ## Local CSV and TSV
35
+
36
+ CSV parsing is a separate package, `@nteract/sift-csv`, so apps that only open
37
+ Parquet or Arrow do not carry it. It converts text or bytes to an Arrow IPC
38
+ stream that `loadTableFile` accepts:
39
+
40
+ ```tsx
41
+ import { csvToArrowIpc } from '@nteract/sift-csv'
42
+ import { loadTableFile, SiftTable } from '@nteract/sift'
43
+
44
+ const load = useCallback(async () => {
45
+ const ipc = await csvToArrowIpc(text, { delimiter: '\t' })
46
+ return loadTableFile(ipc, { format: 'arrow-ipc' })
47
+ }, [text])
48
+
49
+ <SiftTable source={{ kind: 'loader', load }} style={{ height: 600 }} />
50
+ ```
51
+
52
+ Type inference reads the whole file. Booleans, Int64, Float64 (including
53
+ exponents), ISO dates, and ISO timestamps are detected; a column with mixed
54
+ shapes stays text. Empty fields are null in every type. Malformed quoting and
55
+ ragged rows reject with the reason; nothing is truncated or sampled. The host
56
+ owns text decoding and delimiter choice; there is no guessing. Defaults are
57
+ 16 MiB of input, 100,000 rows, and 256 columns, each an option. See the
58
+ package README for the WASM asset setup.
59
+
60
+ ## Local Parquet and Arrow
61
+
62
+ ```ts
63
+ import { loadTableFile, createTable } from '@nteract/sift'
64
+
65
+ const data = await loadTableFile(bytes) // Uint8Array; detects Parquet magic.
66
+ const engine = createTable(container, data)
67
+ // When the document closes or changes:
68
+ engine.destroy() // Also disposes the data's WASM store.
69
+ ```
70
+
71
+ For React, use a memoized loader returning fresh data for every invocation.
72
+ This also supports React StrictMode's setup/cleanup replay:
73
+
74
+ ```tsx
75
+ import { useCallback } from 'react'
76
+ import { loadTableFile, SiftTable } from '@nteract/sift'
77
+
78
+ function ParquetView({ bytes }: { bytes: Uint8Array }) {
79
+ const load = useCallback(() => loadTableFile(bytes), [bytes])
80
+ return <SiftTable source={{ kind: 'loader', load }} style={{ height: 600 }} />
81
+ }
82
+ ```
83
+
84
+ Keep the bytes snapshot stable until the file changes. Do not capture and return
85
+ one previously loaded disposable table from the callback.
86
+
87
+ `loadTableFile` supports Parquet and uncompressed Arrow IPC streams. The optional
88
+ `format` is `'parquet'` or `'arrow-ipc'`. CSV and TSV go through `@nteract/sift-csv`. Arrow file
89
+ containers and compressed IPC streams are not supported by this path.
90
+
91
+ Binary input defaults to 16 MiB, 100,000 rows, 256 columns, and 128 MiB of
92
+ retained Arrow memory (`maxBytes`, `maxRows`, `maxColumns`, `maxDecodedBytes`).
93
+ Rows and columns are checked from file metadata before decoding. Retained memory
94
+ is checked after each decoded batch, and the decoder can allocate one batch past
95
+ the limit before that check runs. These limits are meant for files you chose to
96
+ open, not a sandbox for hostile input: a crafted Parquet file can make one batch
97
+ large. If you load untrusted files, do it in a Worker you can terminate.
98
+
99
+ This API loads a complete file. Virtual scrolling bounds rendered DOM, not the
100
+ dataset: sorting, filtering, and summaries cover every accepted row. There is no
101
+ paging or sampled preview.
102
+
103
+ Lists, structs, and maps display as text. Known image structures have dedicated
104
+ rendering.
105
+
106
+ ## Lifecycle and host controls
107
+
108
+ A `TableData` instance returned by `loadTableFile` owns one WASM store. The React
109
+ loader source creates a fresh store for each setup and discards stale completions;
110
+ the mounted engine disposes the store on teardown. Avoid passing preloaded binary
111
+ data directly to the React `data` prop, because effect replay would reuse a freed
112
+ store. For the imperative API, pass each result to one `createTable` instance. If
113
+ an imperative load is stale or never mounted, call `data.dispose?.()`, using an
114
+ activation token to recognize results completed after switching or closing files.
115
+ Reopen/reload creates fresh data. Do not share disposable data between tables.
116
+
117
+ Sift is a read-only exploration surface. Sorting, filtering, and type casts do
118
+ not rewrite the file. Keep editor text and dirty state in the host; a viewer/editor
119
+ toggle should derive its preview from the current text buffer and preserve edits
120
+ on parse errors or mode changes. Save, Save As/export, reveal-in-folder, file
121
+ watching, dirty-file conflict handling, and loading/error messages remain host
122
+ responsibilities. Parquet can use a view-only mode.
123
+
124
+ For already hosted data, `<SiftTable url="/data.arrow" />` and
125
+ `<SiftTable url="/data.parquet" />` remain available. The URL/manifest paths have
126
+ different loading behavior and do not inherit `loadTableFile` admission limits.
127
+ A sampled Arrow manifest must include its `summary.sampled` and included/total
128
+ row metadata; its sorting, filtering, and summaries cover only the supplied rows.
129
+
130
+ ## Interaction and appearance
131
+
132
+ ```ts
133
+ engine.setSort('age', 'desc')
134
+ engine.setFilter(0, { kind: 'range', min: 18, max: 65 })
135
+ engine.clearAllFilters()
136
+ const state = engine.getState()
137
+ ```
138
+
139
+ The container needs a defined height. The table supplies keyboard navigation and
140
+ ARIA grid semantics.
141
+
142
+ ## Styling
143
+
144
+ `style.css` is compiled and self-contained. It writes nothing to `:root`,
145
+ `html`, or `body` and ships no document-wide CSS reset, so it can load into a host document
146
+ next to the host's own stylesheet. Every rule is keyed on `.sift-root`, which
147
+ Sift puts on the table container and on each element it appends to `<body>`
148
+ (popovers, the column menu, the row detail sheet, the image viewer).
149
+
150
+ Dark mode follows the host: put `.dark` or `data-theme="dark"` on `<html>` or
151
+ `<body>`, so body-mounted overlays receive the same theme.
152
+
153
+ Sift reads eight colors, a font, and a radius. Set them on `<html>` or `<body>`. A table-local wrapper does not theme overlays
154
+ that are portaled to `<body>`:
155
+
156
+ ```css
157
+ :root {
158
+ --sift-color-bg: #fff; /* table background */
159
+ --sift-color-panel: #fff; /* header, popovers, menus, sheets */
160
+ --sift-color-ink: #111; /* text */
161
+ --sift-color-muted: #666; /* secondary text, null markers */
162
+ --sift-color-rule: #e5e5e5; /* borders and grid lines */
163
+ --sift-color-accent: #2563eb; /* histogram bars, selection, focus ring */
164
+ --sift-color-true: #22c55e; /* boolean true */
165
+ --sift-color-false: #ef4444; /* boolean false */
166
+ --sift-font-family: Inter, system-ui, sans-serif;
167
+ --sift-radius-base: 0.5rem;
168
+ }
169
+ ```
170
+
171
+ Every other color (row stripes, scrollbars, badges, skeletons) is derived from
172
+ these with `color-mix()`, so they follow light and dark automatically.
173
+
174
+ The neutrals fall back to the shadcn token names when the host defines them:
175
+ `--background`, `--card`, `--foreground`, `--muted-foreground`, `--border`, and
176
+ `--radius`. A shadcn app gets Sift in its own palette without setting anything.
177
+ Accent and boolean colors keep Sift's defaults unless set, since a shadcn
178
+ `--primary` is a button color and often near-black.
179
+
180
+ ## Notices
181
+
182
+ `lib/THIRD_PARTY_NOTICES.md` lists the Rust crates compiled into the WASM with
183
+ their license texts and NOTICE files. Ship it with any app that redistributes
184
+ Sift. Building and verifying the package from source is covered in the
185
+ package's `AGENTS.md`.
package/lib/LICENSE ADDED
@@ -0,0 +1,28 @@
1
+ BSD 3-Clause License
2
+
3
+ Copyright (c) 2024, runtimed
4
+
5
+ Redistribution and use in source and binary forms, with or without
6
+ modification, are permitted provided that the following conditions are met:
7
+
8
+ 1. Redistributions of source code must retain the above copyright notice, this
9
+ list of conditions and the following disclaimer.
10
+
11
+ 2. Redistributions in binary form must reproduce the above copyright notice,
12
+ this list of conditions and the following disclaimer in the documentation
13
+ and/or other materials provided with the distribution.
14
+
15
+ 3. Neither the name of the copyright holder nor the names of its
16
+ contributors may be used to endorse or promote products derived from
17
+ this software without specific prior written permission.
18
+
19
+ THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
20
+ AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
21
+ IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
22
+ DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
23
+ FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
24
+ DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
25
+ SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
26
+ CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
27
+ OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
28
+ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.