@simplysm/core-browser 13.0.97 → 13.0.98

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 (2) hide show
  1. package/README.md +222 -0
  2. package/package.json +2 -2
package/README.md ADDED
@@ -0,0 +1,222 @@
1
+ # @simplysm/core-browser
2
+
3
+ Core module (browser) -- browser-only utilities including DOM extensions, file downloads, IndexedDB storage, and virtual file system.
4
+
5
+ ## Installation
6
+
7
+ ```bash
8
+ npm install @simplysm/core-browser
9
+ ```
10
+
11
+ ## Side-Effect Imports
12
+
13
+ This package includes side-effect imports that augment global prototypes when the module is loaded:
14
+
15
+ - `import "./extensions/element-ext"` -- Adds methods to `Element.prototype` (`findAll`, `findFirst`, `prependChild`, `getParents`, `findFocusableParent`, `findFirstFocusableChild`, `isOffsetElement`, `isVisible`).
16
+ - `import "./extensions/html-element-ext"` -- Adds methods to `HTMLElement.prototype` (`repaint`, `getRelativeOffset`, `scrollIntoViewIfNeeded`).
17
+
18
+ These side effects run automatically when you import from `@simplysm/core-browser`.
19
+
20
+ ## API Overview
21
+
22
+ ### Extensions -- Element
23
+
24
+ | API | Type | Description |
25
+ |-----|------|-------------|
26
+ | `ElementBounds` | interface | Element bounds info (`target`, `top`, `left`, `width`, `height`) |
27
+ | `copyElement` | function | Copy element content to clipboard via ClipboardEvent |
28
+ | `pasteToElement` | function | Paste clipboard content to element via ClipboardEvent |
29
+ | `getBounds` | function | Get bounds for multiple elements using IntersectionObserver |
30
+ | `Element.findAll` | prototype method | Find all child elements matching a CSS selector |
31
+ | `Element.findFirst` | prototype method | Find first element matching a CSS selector |
32
+ | `Element.prependChild` | prototype method | Insert element as first child |
33
+ | `Element.getParents` | prototype method | Get all parent elements (closest to farthest) |
34
+ | `Element.findFocusableParent` | prototype method | Find first focusable parent element |
35
+ | `Element.findFirstFocusableChild` | prototype method | Find first focusable child element |
36
+ | `Element.isOffsetElement` | prototype method | Check if element has offset positioning |
37
+ | `Element.isVisible` | prototype method | Check if element is visible on screen |
38
+
39
+ ### Extensions -- HTMLElement
40
+
41
+ | API | Type | Description |
42
+ |-----|------|-------------|
43
+ | `HTMLElement.repaint` | prototype method | Force repaint (triggers reflow) |
44
+ | `HTMLElement.getRelativeOffset` | prototype method | Calculate position relative to a parent element |
45
+ | `HTMLElement.scrollIntoViewIfNeeded` | prototype method | Scroll to make target visible if obscured |
46
+
47
+ ### Utils
48
+
49
+ | API | Type | Description |
50
+ |-----|------|-------------|
51
+ | `downloadBlob` | function | Download a Blob as a file |
52
+ | `DownloadProgress` | interface | Download progress info (`receivedLength`, `contentLength`) |
53
+ | `fetchUrlBytes` | function | Download binary data from URL with progress callback |
54
+ | `openFileDialog` | function | Programmatically open file selection dialog |
55
+ | `StoreConfig` | interface | IndexedDB store configuration (`name`, `keyPath`) |
56
+ | `IndexedDbStore` | class | IndexedDB wrapper for key-value storage |
57
+ | `VirtualFsEntry` | interface | Virtual file system entry (`kind`, `dataBase64`) |
58
+ | `IndexedDbVirtualFs` | class | IndexedDB-backed virtual file system |
59
+
60
+ ## `ElementBounds`
61
+
62
+ ```typescript
63
+ interface ElementBounds {
64
+ target: Element;
65
+ top: number;
66
+ left: number;
67
+ width: number;
68
+ height: number;
69
+ }
70
+ ```
71
+
72
+ ## `copyElement`
73
+
74
+ ```typescript
75
+ function copyElement(event: ClipboardEvent): void;
76
+ ```
77
+
78
+ Copy element content to clipboard. Use as a copy event handler.
79
+
80
+ ## `pasteToElement`
81
+
82
+ ```typescript
83
+ function pasteToElement(event: ClipboardEvent): void;
84
+ ```
85
+
86
+ Paste clipboard content to element. Finds the first `input`/`textarea` within the target and replaces its value.
87
+
88
+ ## `getBounds`
89
+
90
+ ```typescript
91
+ async function getBounds(els: Element[], timeout?: number): Promise<ElementBounds[]>;
92
+ ```
93
+
94
+ Get bounds information for elements using IntersectionObserver. Throws `TimeoutError` if no response within `timeout` ms (default: 5000).
95
+
96
+ ## `downloadBlob`
97
+
98
+ ```typescript
99
+ function downloadBlob(blob: Blob, fileName: string): void;
100
+ ```
101
+
102
+ Download a Blob as a file by creating a temporary object URL and clicking a link.
103
+
104
+ ## `DownloadProgress`
105
+
106
+ ```typescript
107
+ interface DownloadProgress {
108
+ receivedLength: number;
109
+ contentLength: number;
110
+ }
111
+ ```
112
+
113
+ ## `fetchUrlBytes`
114
+
115
+ ```typescript
116
+ async function fetchUrlBytes(
117
+ url: string,
118
+ options?: { onProgress?: (progress: DownloadProgress) => void },
119
+ ): Promise<Uint8Array>;
120
+ ```
121
+
122
+ Download binary data from URL with optional progress callback. Pre-allocates memory when Content-Length is known.
123
+
124
+ ## `openFileDialog`
125
+
126
+ ```typescript
127
+ function openFileDialog(options?: {
128
+ accept?: string;
129
+ multiple?: boolean;
130
+ }): Promise<File[] | undefined>;
131
+ ```
132
+
133
+ Programmatically open a file selection dialog. Returns `undefined` if cancelled.
134
+
135
+ ## `StoreConfig`
136
+
137
+ ```typescript
138
+ interface StoreConfig {
139
+ name: string;
140
+ keyPath: string;
141
+ }
142
+ ```
143
+
144
+ ## `IndexedDbStore`
145
+
146
+ ```typescript
147
+ class IndexedDbStore {
148
+ constructor(dbName: string, dbVersion: number, storeConfigs: StoreConfig[]);
149
+ async open(): Promise<IDBDatabase>;
150
+ async withStore<TResult>(
151
+ storeName: string,
152
+ mode: IDBTransactionMode,
153
+ fn: (store: IDBObjectStore) => Promise<TResult>,
154
+ ): Promise<TResult>;
155
+ async get<TValue>(storeName: string, key: IDBValidKey): Promise<TValue | undefined>;
156
+ async put(storeName: string, value: unknown): Promise<void>;
157
+ async delete(storeName: string, key: IDBValidKey): Promise<void>;
158
+ async getAll<TItem>(storeName: string): Promise<TItem[]>;
159
+ close(): void;
160
+ }
161
+ ```
162
+
163
+ IndexedDB wrapper that manages database connections, schema upgrades, and transactional CRUD operations.
164
+
165
+ ## `VirtualFsEntry`
166
+
167
+ ```typescript
168
+ interface VirtualFsEntry {
169
+ kind: "file" | "dir";
170
+ dataBase64?: string;
171
+ }
172
+ ```
173
+
174
+ ## `IndexedDbVirtualFs`
175
+
176
+ ```typescript
177
+ class IndexedDbVirtualFs {
178
+ constructor(db: IndexedDbStore, storeName: string, keyField: string);
179
+ async getEntry(fullKey: string): Promise<VirtualFsEntry | undefined>;
180
+ async putEntry(fullKey: string, kind: "file" | "dir", dataBase64?: string): Promise<void>;
181
+ async deleteByPrefix(keyPrefix: string): Promise<boolean>;
182
+ async listChildren(prefix: string): Promise<{ name: string; isDirectory: boolean }[]>;
183
+ async ensureDir(fullKeyBuilder: (path: string) => string, dirPath: string): Promise<void>;
184
+ }
185
+ ```
186
+
187
+ Virtual file system backed by IndexedDB. Stores files and directories as key-value entries with hierarchical path support.
188
+
189
+ ## Usage Examples
190
+
191
+ ### Download a file
192
+
193
+ ```typescript
194
+ import { downloadBlob } from "@simplysm/core-browser";
195
+
196
+ const blob = new Blob(["Hello"], { type: "text/plain" });
197
+ downloadBlob(blob, "hello.txt");
198
+ ```
199
+
200
+ ### Open file dialog and read files
201
+
202
+ ```typescript
203
+ import { openFileDialog } from "@simplysm/core-browser";
204
+
205
+ const files = await openFileDialog({ accept: ".csv", multiple: true });
206
+ if (files) {
207
+ for (const file of files) {
208
+ const text = await file.text();
209
+ }
210
+ }
211
+ ```
212
+
213
+ ### Use IndexedDB store
214
+
215
+ ```typescript
216
+ import { IndexedDbStore } from "@simplysm/core-browser";
217
+
218
+ const store = new IndexedDbStore("myApp", 1, [{ name: "settings", keyPath: "key" }]);
219
+ await store.put("settings", { key: "theme", value: "dark" });
220
+ const item = await store.get<{ key: string; value: string }>("settings", "theme");
221
+ store.close();
222
+ ```
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@simplysm/core-browser",
3
- "version": "13.0.97",
3
+ "version": "13.0.98",
4
4
  "description": "Simplysm package - Core module (browser)",
5
5
  "author": "simplysm",
6
6
  "license": "Apache-2.0",
@@ -24,7 +24,7 @@
24
24
  ],
25
25
  "dependencies": {
26
26
  "tabbable": "^6.4.0",
27
- "@simplysm/core-common": "13.0.97"
27
+ "@simplysm/core-common": "13.0.98"
28
28
  },
29
29
  "devDependencies": {
30
30
  "happy-dom": "^20.8.4"