@usefillo/dom 0.17.0 → 0.19.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
@@ -65,7 +65,7 @@ Or drop it in with a single script tag — the bundle exposes a global `Fillo`:
65
65
  </script>
66
66
  ```
67
67
 
68
- The default stylesheet follows system dark mode for unthemed embeds. Pass `theme: { colorScheme: "dark" }` or `"light"` when the host surface is known.
68
+ The default stylesheet inherits the host page's CSS `color-scheme` and font. If your theme switch only toggles a class or data attribute, pass its resolved mode as `theme: { colorScheme: "light" | "dark" }`. Use `"auto"` only for a deliberately system-driven page. A fixed hex `background` automatically selects a readable palette unless you explicitly choose one.
69
69
 
70
70
  Every rendered part carries `data-*` state attributes (`data-selected`, `data-invalid`, …) for utility CSS, and the default stylesheet is cascade-layered so your own styles win. On Tailwind v3 or reset-heavy sites import `@usefillo/dom/styles.unlayered.css` instead. Styling contract: [fillo.so/docs/styling](https://fillo.so/docs/styling).
71
71
 
package/dist/index.js CHANGED
@@ -1662,7 +1662,10 @@ function repeatingGroup(context) {
1662
1662
  removeBtn.toggleAttribute("disabled", !canRemove);
1663
1663
  if (!canRemove) {
1664
1664
  removeBtn.setAttribute("aria-disabled", "true");
1665
- removeBtn.setAttribute("title", `At least ${floor} ${floor === 1 ? "entry" : "entries"} required`);
1665
+ removeBtn.setAttribute(
1666
+ "title",
1667
+ `At least ${floor} ${floor === 1 ? "entry" : "entries"} required`
1668
+ );
1666
1669
  }
1667
1670
  removeBtn.addEventListener("click", () => {
1668
1671
  if (count <= floor) return;
@@ -1969,6 +1972,8 @@ var DomFormController = class {
1969
1972
  * substitutes for the explicit uploadsAvailable control state. */
1970
1973
  syncWarningCode;
1971
1974
  syncWarningUrl;
1975
+ /** Dashboard form overview containing the Publish action — dev chrome only. */
1976
+ syncFormUrl;
1972
1977
  /** Server-authoritative ability to start a new file upload. */
1973
1978
  uploadsAvailable;
1974
1979
  /** Server-authoritative per-file ceiling for the active storage lane. */
@@ -1994,6 +1999,7 @@ var DomFormController = class {
1994
1999
  const result = await syncCodeForm(client, codeForm, { bypassCache: true });
1995
2000
  this.syncWarningCode = result.warningCode;
1996
2001
  this.syncWarningUrl = result.warningUrl;
2002
+ this.syncFormUrl = result.manageUrl;
1997
2003
  this.uploadsAvailable = result.uploadsAvailable;
1998
2004
  this.uploadFileSizeLimitMb = result.uploadFileSizeLimitMb;
1999
2005
  if (result.status === "draft") {
@@ -2094,6 +2100,7 @@ var DomFormController = class {
2094
2100
  this.draftNotice = result.status === "draft";
2095
2101
  this.syncWarningCode = result.warningCode;
2096
2102
  this.syncWarningUrl = result.warningUrl;
2103
+ this.syncFormUrl = result.manageUrl;
2097
2104
  this.uploadsAvailable = result.uploadsAvailable;
2098
2105
  this.uploadFileSizeLimitMb = result.uploadFileSizeLimitMb;
2099
2106
  this.challenge = this.options.challenge ?? result.challenge;
@@ -2424,7 +2431,7 @@ var DomFormController = class {
2424
2431
  } catch (error) {
2425
2432
  if (this.destroyed || controller.signal.aborted) return;
2426
2433
  const uploadError = toFilloError(error);
2427
- const message = uploadError.status !== void 0 && uploadError.status >= 500 ? DEFAULT_FIELD_STRINGS.uploadUnavailable : uploadError.message || DEFAULT_FIELD_STRINGS.uploadFailed;
2434
+ const message = uploadError.status === 0 || uploadError.status !== void 0 && uploadError.status >= 500 ? DEFAULT_FIELD_STRINGS.uploadUnavailable : DEFAULT_FIELD_STRINGS.uploadFailed;
2428
2435
  const row = this.inFlight.get(key);
2429
2436
  if (row) row.error = message;
2430
2437
  this.announceAlert(message);
@@ -2992,6 +2999,7 @@ var DomFormController = class {
2992
2999
  staged: this.stagedNotice,
2993
3000
  draft: this.draftNotice,
2994
3001
  warningUrl: this.syncWarningUrl,
3002
+ formUrl: this.syncFormUrl,
2995
3003
  noClient: !this.options.client && !this.options.renderOnly
2996
3004
  })
2997
3005
  );
@@ -3371,25 +3379,45 @@ function devSyncErrorEl(error) {
3371
3379
  attrs: { role: "alert" }
3372
3380
  });
3373
3381
  }
3374
- function devStagedEl() {
3375
- return el("div", {
3376
- className: "fillo-devwarning",
3377
- text: "Code changes are staged. Local preview only. Publish in Fillo before deploying for respondents.",
3378
- attrs: { role: "alert" }
3379
- });
3382
+ function devStagedEl(formUrl) {
3383
+ const node = el("div", { className: "fillo-devwarning", attrs: { role: "alert" } });
3384
+ node.append(
3385
+ "Code changes are staged, not live. This page shows your draft, while respondents still get the live version. "
3386
+ );
3387
+ const publishUrl = safeHttpUrl(formUrl);
3388
+ if (publishUrl) {
3389
+ node.appendChild(
3390
+ el("a", {
3391
+ text: "Review and publish in Fillo",
3392
+ attrs: { href: publishUrl, target: "_blank", rel: "noopener noreferrer" }
3393
+ })
3394
+ );
3395
+ node.append(".");
3396
+ } else {
3397
+ node.append("Review and publish the changes in Fillo.");
3398
+ }
3399
+ return node;
3380
3400
  }
3381
- function devDraftEl(warningUrl) {
3401
+ function devDraftEl(warningUrl, formUrl) {
3382
3402
  const node = el("div", { className: "fillo-devwarning", attrs: { role: "alert" } });
3383
3403
  node.append(
3384
- "Draft form \u2014 it renders here, but it won't accept responses until you publish it in your Fillo dashboard. "
3404
+ "Draft form preview \u2014 the form renders for local testing, but Fillo will reject the submission and save no response until you publish it. "
3385
3405
  );
3386
- const safeUrl = safeHttpUrl(warningUrl);
3387
- if (safeUrl) {
3388
- node.append("Connect storage to publish: ");
3406
+ const storageUrl = safeHttpUrl(warningUrl);
3407
+ const publishUrl = safeHttpUrl(formUrl);
3408
+ if (storageUrl) {
3409
+ node.appendChild(
3410
+ el("a", {
3411
+ text: "Connect storage to publish",
3412
+ attrs: { href: storageUrl, target: "_blank", rel: "noopener noreferrer" }
3413
+ })
3414
+ );
3415
+ node.append(". ");
3416
+ } else if (publishUrl) {
3389
3417
  node.appendChild(
3390
3418
  el("a", {
3391
- text: safeUrl,
3392
- attrs: { href: safeUrl, target: "_blank", rel: "noopener noreferrer" }
3419
+ text: "Open in Fillo to publish",
3420
+ attrs: { href: publishUrl, target: "_blank", rel: "noopener noreferrer" }
3393
3421
  })
3394
3422
  );
3395
3423
  node.append(". ");
@@ -3417,8 +3445,8 @@ function devChromeEls(state) {
3417
3445
  if (state.preview) nodes.push(previewBadgeEl());
3418
3446
  if (state.devNotices === false) return nodes;
3419
3447
  if (state.syncError) nodes.push(devSyncErrorEl(state.syncError));
3420
- else if (state.staged) nodes.push(devStagedEl());
3421
- else if (state.draft) nodes.push(devDraftEl(state.warningUrl));
3448
+ else if (state.staged) nodes.push(devStagedEl(state.formUrl));
3449
+ else if (state.draft) nodes.push(devDraftEl(state.warningUrl, state.formUrl));
3422
3450
  else if (state.noClient) nodes.push(devNoClientEl());
3423
3451
  return nodes;
3424
3452
  }