hyperclayjs 1.24.5 → 1.25.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 CHANGED
@@ -80,7 +80,7 @@ import 'hyperclayjs/presets/standard.js';
80
80
  | onaftersave | 1KB | [onaftersave] attribute - run JS when save status changes |
81
81
  | refetch-on-save | 0.9KB | Flash-free refetch of href/src resources on save via [refetch-on-save] attribute |
82
82
  | save-freeze | 2.8KB | [save-freeze] attribute - freeze element innerHTML for saves, live DOM changes freely |
83
- | sortable | 3.4KB | Drag-drop sorting with [sortable], lazy-loads ~118KB Sortable.js in edit mode |
83
+ | sortable | 3.3KB | Drag-drop sorting with [sortable], lazy-loads ~118KB Sortable.js in edit mode |
84
84
 
85
85
  ### UI Components (User interface elements)
86
86
 
@@ -122,7 +122,7 @@ import 'hyperclayjs/presets/standard.js';
122
122
 
123
123
  | Module | Size | Description |
124
124
  |--------|------|-------------|
125
- | file-upload | 10.7KB | File upload with progress |
125
+ | file-upload | 11.3KB | File upload with progress |
126
126
  | live-sync | 11.6KB | Real-time DOM sync across browsers |
127
127
  | send-message | 1.3KB | Message sending utility |
128
128
 
@@ -144,7 +144,7 @@ Standard feature set for most use cases
144
144
 
145
145
  **Modules:** `save-core`, `snapshot`, `save-system`, `unsaved-warning`, `edit-mode-helpers`, `persist`, `option-visibility`, `event-attrs`, `dom-helpers`, `toast`, `save-toast`, `export-to-window`, `view-mode-excludes-edit-modules`
146
146
 
147
- ### Everything (~224.9KB)
147
+ ### Everything (~225.4KB)
148
148
  All available features
149
149
 
150
150
  Includes all available modules across all categories.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "hyperclayjs",
3
- "version": "1.24.5",
3
+ "version": "1.25.0",
4
4
  "description": "Modular JavaScript library for building interactive malleable HTML files with Hyperclay",
5
5
  "type": "module",
6
6
  "main": "src/hyperclay.js",
@@ -23,7 +23,7 @@
23
23
  "src"
24
24
  ],
25
25
  "scripts": {
26
- "deploy": "npx wrangler deploy",
26
+ "deploy": "npx wrangler deploy && git rev-parse HEAD > .deploy",
27
27
  "dev": "npm run build && npm run build:website && http-server website -p 3535 -c-1 -o /index.html",
28
28
  "build": "npm run generate:deps && npm run build:loader && npm run build:readme && npm run build:load-jsdelivr && npm run build:index-url && npm run build:llms-txt",
29
29
  "build:llms-txt": "node build/build-llms-txt.js",
@@ -2,21 +2,42 @@ import toast from "../ui/toast.js";
2
2
  import debounce from "../utilities/debounce.js";
3
3
  import copyToClipboard from "../string-utilities/copy-to-clipboard.js";
4
4
 
5
- const MAX_FILE_SIZE = 10 * 1024 * 1024; // 10MB
5
+ function getMaxFileSize() {
6
+ return window.env?.MAX_UPLOAD_SIZE || 10 * 1024 * 1024;
7
+ }
6
8
 
7
9
  export function uploadFile(eventOrFile, callback = () => {}, extraData = {}) {
8
- // handle event
9
10
  if (eventOrFile instanceof Event) {
10
11
  eventOrFile.preventDefault();
11
12
  const fileInput = eventOrFile.target;
12
- const file = fileInput.files[0];
13
- return uploadFileFromObject(file, res => {
14
- callback(res);
15
- fileInput.value = ""; // Reset fileInput after upload
16
- }, extraData);
13
+ const files = Array.from(fileInput.files);
14
+
15
+ if (files.length === 0) return Promise.reject(new Error('No files selected'));
16
+
17
+ if (files.length === 1) {
18
+ return uploadFileFromObject(files[0], res => {
19
+ callback(res);
20
+ fileInput.value = "";
21
+ }, extraData);
22
+ }
23
+
24
+ return (async () => {
25
+ const results = [];
26
+ for (let i = 0; i < files.length; i++) {
27
+ try {
28
+ const result = await uploadFileFromObject(files[i], () => {}, extraData);
29
+ results.push(result);
30
+ } catch (err) {
31
+ results.push({ error: err.message, fileName: files[i].name });
32
+ }
33
+ toast(`Uploaded ${i + 1} of ${files.length} files`);
34
+ }
35
+ fileInput.value = "";
36
+ callback(results);
37
+ return results;
38
+ })();
17
39
  }
18
40
 
19
- // handle raw file object
20
41
  if (eventOrFile instanceof File) {
21
42
  return uploadFileFromObject(eventOrFile, callback, extraData);
22
43
  }
@@ -65,7 +86,7 @@ export function uploadFileBasic (eventOrFile, {
65
86
  onError = (error) => {}
66
87
  } = {}) {
67
88
  function handleUpload(file) {
68
- if (file.size > MAX_FILE_SIZE) {
89
+ if (file.size > getMaxFileSize()) {
69
90
  onError(new Error('File too large'));
70
91
  return Promise.reject(new Error('File too large'));
71
92
  }
@@ -118,8 +139,9 @@ export function uploadFileBasic (eventOrFile, {
118
139
  }
119
140
 
120
141
  function uploadFileFromObject(file, onComplete = () => {}, extraData = {}) {
121
- if (file.size > MAX_FILE_SIZE) {
122
- toast(`Maximum file size: ${MAX_FILE_SIZE / 1024 / 1024}MB`, 'error');
142
+ const maxFileSize = getMaxFileSize();
143
+ if (file.size > maxFileSize) {
144
+ toast(`Maximum file size: ${maxFileSize / 1024 / 1024}MB`, 'error');
123
145
  return Promise.reject(new Error('File too large'));
124
146
  }
125
147
 
@@ -188,6 +210,7 @@ function uploadFileData(fileName, fileBody, progressCallback, extraData = {}) {
188
210
  const xhr = new XMLHttpRequest();
189
211
  xhr.open("POST", "/upload", true);
190
212
  xhr.setRequestHeader("Content-Type", "application/json");
213
+ xhr.setRequestHeader("Page-URL", window.location.href);
191
214
 
192
215
  let lastReportedProgress = 0;
193
216
  const debouncedProgressCallback = debounce(function (event) {
@@ -11,13 +11,12 @@
11
11
  - e.g. <ul sortable onsorted="console.log('Items reordered!')"></ul>
12
12
 
13
13
  This wrapper conditionally loads the full Sortable.js vendor script (~118KB)
14
- only when in edit mode. The script is injected with save-remove so it's
15
- stripped from the page before saving.
14
+ only when in edit mode, using dynamic import().
16
15
 
17
16
  */
18
17
  import { isEditMode } from "../core/isAdminOfCurrentResource.js";
19
18
  import Mutation from "../utilities/mutation.js";
20
- import { loadVendorScript, getVendorUrl } from "../utilities/loadVendorScript.js";
19
+ import { getVendorUrl } from "../utilities/loadVendorScript.js";
21
20
 
22
21
  function makeSortable(sortableElem, Sortable) {
23
22
  let options = {};
@@ -75,7 +74,8 @@ async function init() {
75
74
 
76
75
  // Load the vendor script
77
76
  const vendorUrl = getVendorUrl(import.meta.url, '../vendor/Sortable.vendor.js');
78
- const Sortable = await loadVendorScript(vendorUrl, 'Sortable');
77
+ await import(vendorUrl);
78
+ const Sortable = window.Sortable;
79
79
 
80
80
  // Auto-export to window unless suppressed by loader
81
81
  if (!window.__hyperclayNoAutoExport) {
package/src/hyperclay.js CHANGED
@@ -1,7 +1,7 @@
1
1
  /**
2
2
  * DO NOT EDIT THIS FILE DIRECTLY — it is generated from build/hyperclay.template.js
3
3
  *
4
- * HyperclayJS v1.24.5 - Minimal Browser-Native Loader
4
+ * HyperclayJS v1.25.0 - Minimal Browser-Native Loader
5
5
  *
6
6
  * Modules auto-init when imported (no separate init call needed).
7
7
  * Include `export-to-window` feature to export to window.hyperclay.
@@ -433,6 +433,7 @@ const modalCss = `<style class="micromodal-css">
433
433
  padding: 6px 6px 7px;
434
434
  font-size: var(--hyperclay-modal-input-font-size, 16px);
435
435
  color: #000;
436
+ background: #fff;
436
437
  }
437
438
 
438
439
  .micromodal .micromodal__input:focus, .micromodal .micromodal__input:active {