selfstore 1.8.18 → 1.8.20

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.
@@ -1,4 +1,4 @@
1
- import { B as BackupTarget, P as PeerSource } from './store-Cs6QIzzG.js';
1
+ import { B as BackupTarget, P as PeerSource } from './store-DhrWMYg_.js';
2
2
  import { K as KV } from './cache-ilsK3Tki.js';
3
3
 
4
4
  /**
@@ -566,8 +566,16 @@ interface LocalStore {
566
566
  detachTarget(opts?: {
567
567
  keepSession?: boolean;
568
568
  }): Promise<void>;
569
- /** Build the portable .selfstore blob (for a manual download or dated copy). */
570
- exportBlob(): Promise<Blob>;
569
+ /** Build the portable .selfstore blob (for a manual download or dated copy).
570
+ *
571
+ * `plaintext` writes a READABLE copy even when the store is protected: the
572
+ * same ZIP, with `selfstore.json` in the clear, for someone who wants to
573
+ * read, inspect or move their own data. It changes nothing about the store
574
+ * or its destination - the real backup stays encrypted. Refused while
575
+ * locked, and refused outright on a `requireEncryption` store. */
576
+ exportBlob(opts?: {
577
+ plaintext?: boolean;
578
+ }): Promise<Blob>;
571
579
  /** Mark the file-manual pending download as resolved. */
572
580
  markDownloaded(): void;
573
581
  /** Stop persisting (shared computer). */
package/dist/widgets.d.ts CHANGED
@@ -1,11 +1,11 @@
1
- import { S as StoreLike, F as FlowHost, C as ConnectTargets, a as ConnectFlowOptions, b as ConnectKind, c as ConnectFlow } from './connect-BTVzRJY8.js';
1
+ import { S as StoreLike, F as FlowHost, C as ConnectTargets, a as ConnectFlowOptions, b as ConnectKind, c as ConnectFlow } from './connect-GY1R9c6Q.js';
2
2
  import { ShareEngine, ShareLevel, ShareFlow, JoinEngine, JoinFlow, ReplicaFlow } from './flows.js';
3
- import { f as BackupsManager } from './manager-DhoIbJyg.js';
4
- import './store-Cs6QIzzG.js';
3
+ import { f as BackupsManager } from './manager-BlSs6Q5S.js';
4
+ import './store-DhrWMYg_.js';
5
5
  import './cache-ilsK3Tki.js';
6
6
  import './sync.js';
7
- import './drive-CY_Vsj7V.js';
8
- import './s3-0qqIyphl.js';
7
+ import './drive-BLRsK32w.js';
8
+ import './s3-BLgf6hqR.js';
9
9
  import './machine-ALMkT3mk.js';
10
10
 
11
11
  /** Flat key -> string map; widgets merge a partial override over EN defaults. */
@@ -576,6 +576,7 @@ declare class SelfstoreGateElement extends FlowWidget {
576
576
  constructor();
577
577
  attributeChangedCallback(name: string): void;
578
578
  connectedCallback(): void;
579
+ disconnectedCallback(): void;
579
580
  private host;
580
581
  private wire;
581
582
  /** The library already derives "no durable home yet" - asking the target
@@ -831,10 +832,36 @@ declare class SelfstoreAccountElement extends FlowWidget {
831
832
  * file on the device, a server for WebDAV, a bucket for object storage. */
832
833
  declare const defaultIcons: Record<ConnectKind, string>;
833
834
 
834
- /** Register the elements as <PREFIX-connect>, <PREFIX-share>, <PREFIX-join>,
835
- * <PREFIX-status>, <PREFIX-backups>, <PREFIX-gate> and
836
- * <PREFIX-destination> (default prefix 'selfstore'). Safe to call twice;
837
- * throws in environments without custom elements (browser code only). */
835
+ /** Register <PREFIX-connect>: the "where does my data live" journey. */
836
+ declare function defineConnect(prefix?: string): void;
837
+ /** Register <PREFIX-status>: the live storage status line. */
838
+ declare function defineStatus(prefix?: string): void;
839
+ /** Register <PREFIX-share>: publishing an invitation. */
840
+ declare function defineShare(prefix?: string): void;
841
+ /** Register <PREFIX-join>: accepting an invitation. */
842
+ declare function defineJoin(prefix?: string): void;
843
+ /** Register <PREFIX-backups>: the named-backup manager. */
844
+ declare function defineBackups(prefix?: string): void;
845
+ /** Register <PREFIX-gate>, the blocking first-run screen, with the
846
+ * <PREFIX-connect> child it builds for itself. */
847
+ declare function defineGate(prefix?: string): void;
848
+ /** Register <PREFIX-destination>, the storage panel, with the connect and
849
+ * status elements it composes. */
850
+ declare function defineDestination(prefix?: string): void;
851
+ /** Register <PREFIX-storage>: the whole journey in one tag. It chooses between
852
+ * the gate and the destination panel from the engine's own status, so both
853
+ * come with it. */
854
+ declare function defineStorage(prefix?: string): void;
855
+ /** Register <PREFIX-account>, the header control, with the status row it
856
+ * composes for anything needing attention. */
857
+ declare function defineAccount(prefix?: string): void;
858
+ /** Register all nine elements at once (default prefix 'selfstore'). Safe to
859
+ * call twice; throws in environments without custom elements (browser code
860
+ * only).
861
+ *
862
+ * Convenient, and the reason a small app ships every widget: naming all nine
863
+ * here is what pins them in the bundle. Reach for the single-widget functions
864
+ * above when size matters. */
838
865
  declare function defineSelfstoreWidgets(prefix?: string): void;
839
866
 
840
- export { type BackupsAction, type DestinationAction, FlowWidget, SelfstoreAccountElement, SelfstoreBackupsElement, SelfstoreConnectElement, SelfstoreDestinationElement, SelfstoreGateElement, SelfstoreJoinElement, SelfstoreShareElement, SelfstoreStatusElement, SelfstoreStorageElement, type ShareAction, type WebdavPreset, type WidgetLabels, defaultIcons, defineSelfstoreWidgets };
867
+ export { type BackupsAction, type DestinationAction, FlowWidget, SelfstoreAccountElement, SelfstoreBackupsElement, SelfstoreConnectElement, SelfstoreDestinationElement, SelfstoreGateElement, SelfstoreJoinElement, SelfstoreShareElement, SelfstoreStatusElement, SelfstoreStorageElement, type ShareAction, type WebdavPreset, type WidgetLabels, defaultIcons, defineAccount, defineBackups, defineConnect, defineDestination, defineGate, defineJoin, defineSelfstoreWidgets, defineShare, defineStatus, defineStorage };
package/dist/widgets.js CHANGED
@@ -43,8 +43,13 @@ var baseStyles = `
43
43
  --_radius: var(--selfstore-radius, 12px);
44
44
  --_gap: var(--selfstore-gap, 0.6rem);
45
45
  --_danger: var(--selfstore-danger, #dc2626);
46
- --_ok: var(--selfstore-ok, #16a34a);
47
- --_warn: var(--selfstore-warn, #d97706);
46
+ /* Severity colors are read as TEXT (see sev-* below), so they answer to the
47
+ 4.5:1 text threshold, not the 3:1 one for a graphic. The obvious green and
48
+ amber of a palette sit at 3.3:1 and 3.2:1 on white and fail it: a status
49
+ line is exactly the sentence someone needs to read. One step darker each
50
+ clears it at 5.0:1 without changing which color anyone thinks they see. */
51
+ --_ok: var(--selfstore-ok, #15803d);
52
+ --_warn: var(--selfstore-warn, #b45309);
48
53
  }
49
54
  /* Status severity, as a text color the dot inherits (background: currentColor). */
50
55
  [part~='sev-ok'] { color: var(--_ok); }
@@ -155,6 +160,12 @@ span[part~='status-glyph'] {
155
160
  animation: ss-spin 0.8s linear infinite;
156
161
  }
157
162
  @keyframes ss-spin { to { transform: rotate(360deg); } }
163
+ /* An endless spin is the one motion here, and it runs during the wait someone
164
+ with vestibular trouble cannot escape. Keep the shape as the busy signal,
165
+ drop the rotation. */
166
+ @media (prefers-reduced-motion: reduce) {
167
+ [part='spinner'] { animation: none; border-top-color: var(--_border); }
168
+ }
158
169
  button[part~='button'] {
159
170
  font: inherit;
160
171
  padding: 0.45rem 0.9rem;
@@ -1019,7 +1030,7 @@ var SelfstoreConnectElement = class extends FlowWidget {
1019
1030
  h("div", { part: "title" }, this.t("connect.password.title")),
1020
1031
  h("div", { part: "hint" }, this.t("connect.password.hint")),
1021
1032
  field,
1022
- s.passwordError ? h("div", { part: "error-note" }, this.t("connect.password.wrong")) : null,
1033
+ s.passwordError ? h("div", { part: "error-note", role: "alert" }, this.t("connect.password.wrong")) : null,
1023
1034
  h(
1024
1035
  "div",
1025
1036
  { part: "row" },
@@ -1632,7 +1643,9 @@ var SelfstoreShareElement = class extends FlowWidget {
1632
1643
  put(into, this.heading("title", "share.title"));
1633
1644
  if (s.stale) into.append(h("div", { part: "hint" }, this.t("share.stale")));
1634
1645
  if (s.error && !s.stale) {
1635
- into.append(h("div", { part: "error-note" }, this.errorText(s.error.labelKey)));
1646
+ into.append(
1647
+ h("div", { part: "error-note", role: "alert" }, this.errorText(s.error.labelKey))
1648
+ );
1636
1649
  }
1637
1650
  if (this.#withCreate) {
1638
1651
  const missing = this.#levels.filter((l) => !s.links.some((k) => k.level === l));
@@ -2118,6 +2131,7 @@ var FR5 = {
2118
2131
  "status.action.reconnect": "Retrouver l'acc\xE8s",
2119
2132
  "status.action.unlock": "D\xE9verrouiller"
2120
2133
  };
2134
+ var GLYPH = { ok: "\u2713", warn: "!", danger: "!", info: "" };
2121
2135
  var SelfstoreStatusElement = class extends FlowWidget {
2122
2136
  static get observedAttributes() {
2123
2137
  return ["variant"];
@@ -2146,6 +2160,7 @@ var SelfstoreStatusElement = class extends FlowWidget {
2146
2160
  }
2147
2161
  connectedCallback() {
2148
2162
  super.connectedCallback();
2163
+ if (!this.hasAttribute("role")) this.setAttribute("role", "status");
2149
2164
  if (this.hasAttribute("variant"))
2150
2165
  this.variant = this.getAttribute("variant");
2151
2166
  this.follow(this.hostOf());
@@ -2174,7 +2189,6 @@ var SelfstoreStatusElement = class extends FlowWidget {
2174
2189
  part: `status-dot sev-${status.severity}`,
2175
2190
  "aria-hidden": "true"
2176
2191
  });
2177
- const GLYPH = { ok: "\u2713", warn: "!", danger: "!", info: "" };
2178
2192
  const glyph = GLYPH[status.severity];
2179
2193
  const sign = glyph ? h("span", { part: `status-glyph sev-${status.severity}`, "aria-hidden": "true" }, glyph) : dot;
2180
2194
  if (this.#variant === "dot") {
@@ -2944,7 +2958,7 @@ var SelfstoreBackupsElement = class extends FlowWidget {
2944
2958
  this.rerender();
2945
2959
  }
2946
2960
  }),
2947
- taken ? h("div", { part: "error-note" }, this.t("backups.taken")) : clean ? h(
2961
+ taken ? h("div", { part: "error-note", role: "alert" }, this.t("backups.taken")) : clean ? h(
2948
2962
  "div",
2949
2963
  { part: "sub" },
2950
2964
  this.ts("backups.willBe", { file: this.#manager?.fileNameFor(clean) ?? "" })
@@ -3002,7 +3016,7 @@ var SelfstoreBackupsElement = class extends FlowWidget {
3002
3016
  this.rerender();
3003
3017
  }
3004
3018
  }),
3005
- taken ? h("div", { part: "error-note" }, this.t("backups.taken")) : clean ? h(
3019
+ taken ? h("div", { part: "error-note", role: "alert" }, this.t("backups.taken")) : clean ? h(
3006
3020
  "div",
3007
3021
  { part: "sub" },
3008
3022
  this.ts("backups.willBe", { file: this.#manager?.fileNameFor(clean) ?? "" })
@@ -3109,7 +3123,7 @@ var SelfstoreBackupsElement = class extends FlowWidget {
3109
3123
  this.t(`backups.replica.dest.${kind}`)
3110
3124
  )
3111
3125
  ),
3112
- snap.error ? h("div", { part: "error-note" }, this.t("error.generic")) : null,
3126
+ snap.error ? h("div", { part: "error-note", role: "alert" }, this.t("error.generic")) : null,
3113
3127
  h(
3114
3128
  "button",
3115
3129
  {
@@ -3161,7 +3175,7 @@ var SelfstoreBackupsElement = class extends FlowWidget {
3161
3175
  c.password,
3162
3176
  (v) => c.password = v
3163
3177
  ),
3164
- snap.error ? h("div", { part: "error-note" }, this.t("error.generic")) : null,
3178
+ snap.error ? h("div", { part: "error-note", role: "alert" }, this.t("error.generic")) : null,
3165
3179
  h(
3166
3180
  "div",
3167
3181
  { part: "row", style: "margin-top:0.45rem" },
@@ -3218,7 +3232,7 @@ var SelfstoreBackupsElement = class extends FlowWidget {
3218
3232
  c.secretAccessKey,
3219
3233
  (v) => c.secretAccessKey = v
3220
3234
  ),
3221
- snap.error ? h("div", { part: "error-note" }, this.t("error.generic")) : null,
3235
+ snap.error ? h("div", { part: "error-note", role: "alert" }, this.t("error.generic")) : null,
3222
3236
  h(
3223
3237
  "div",
3224
3238
  { part: "row", style: "margin-top:0.45rem" },
@@ -3628,6 +3642,11 @@ var SelfstoreGateElement = class extends FlowWidget {
3628
3642
  if (deferrable !== null) this.deferrable = deferrable;
3629
3643
  this.wire();
3630
3644
  }
3645
+ disconnectedCallback() {
3646
+ super.disconnectedCallback();
3647
+ document.removeEventListener("focusin", this.#keepFocus);
3648
+ this.#focusBefore = null;
3649
+ }
3631
3650
  host() {
3632
3651
  const s = this.#store;
3633
3652
  if (!s) return null;
@@ -3650,13 +3669,46 @@ var SelfstoreGateElement = class extends FlowWidget {
3650
3669
  if (!host.engine.state.ready) return false;
3651
3670
  return host.engine.state.status.action === "choose-destination";
3652
3671
  }
3672
+ /** Where focus was when the gate took over, so it can be handed back. */
3673
+ #focusBefore = null;
3674
+ /** `aria-modal` tells assistive tech this is modal; it does NOT stop the Tab
3675
+ * key. Without this, a keyboard user tabs straight out of a screen whose
3676
+ * whole purpose is to block, and lands in the application behind it -
3677
+ * invisibly, since the gate still covers what they are now driving.
3678
+ *
3679
+ * A guard rather than a cycle through the focusable elements: the gate
3680
+ * contains a `<selfstore-connect>` with its own shadow root, and walking
3681
+ * focusables across shadow boundaries is the kind of code that quietly
3682
+ * stops matching the DOM it walks. Anything landing outside comes straight
3683
+ * back to the card, which is correct whatever the widget grows inside. */
3684
+ #pulling = false;
3685
+ #keepFocus = (e) => {
3686
+ if (!this.#open || this.#pulling) return;
3687
+ if (e.composedPath().includes(this)) return;
3688
+ const card = this.root.querySelector('[part~="gate-card"]');
3689
+ if (!card) return;
3690
+ this.#pulling = true;
3691
+ try {
3692
+ card.focus();
3693
+ } finally {
3694
+ this.#pulling = false;
3695
+ }
3696
+ };
3653
3697
  sync() {
3654
3698
  const open = this.shouldOpen();
3655
3699
  if (open === this.#open) return;
3656
3700
  this.#open = open;
3657
3701
  if (!open) this.#connect = null;
3658
3702
  super.rerender();
3659
- if (open) this.root.querySelector('[part~="gate-card"]')?.focus();
3703
+ if (open) {
3704
+ this.#focusBefore = document.activeElement ?? null;
3705
+ document.addEventListener("focusin", this.#keepFocus);
3706
+ this.root.querySelector('[part~="gate-card"]')?.focus();
3707
+ return;
3708
+ }
3709
+ document.removeEventListener("focusin", this.#keepFocus);
3710
+ this.#focusBefore?.focus?.();
3711
+ this.#focusBefore = null;
3660
3712
  }
3661
3713
  /** Rebuilding the frame would re-append the child connect element, and a
3662
3714
  * custom element that leaves the DOM and comes back rebuilds its flow: a
@@ -4529,21 +4581,62 @@ var SelfstoreAccountElement = class extends FlowWidget {
4529
4581
  };
4530
4582
 
4531
4583
  // src/entries/widgets.ts
4584
+ function register(prefix, tags) {
4585
+ for (const [name, ctor] of Object.entries(tags)) {
4586
+ const tag = `${prefix}-${name}`;
4587
+ if (!customElements.get(tag)) customElements.define(tag, ctor);
4588
+ }
4589
+ }
4590
+ function defineConnect(prefix = "selfstore") {
4591
+ register(prefix, { connect: SelfstoreConnectElement });
4592
+ }
4593
+ function defineStatus(prefix = "selfstore") {
4594
+ register(prefix, { status: SelfstoreStatusElement });
4595
+ }
4596
+ function defineShare(prefix = "selfstore") {
4597
+ register(prefix, { share: SelfstoreShareElement });
4598
+ }
4599
+ function defineJoin(prefix = "selfstore") {
4600
+ register(prefix, { join: SelfstoreJoinElement });
4601
+ }
4602
+ function defineBackups(prefix = "selfstore") {
4603
+ register(prefix, { backups: SelfstoreBackupsElement });
4604
+ }
4605
+ function defineGate(prefix = "selfstore") {
4606
+ register(prefix, { connect: SelfstoreConnectElement, gate: SelfstoreGateElement });
4607
+ }
4608
+ function defineDestination(prefix = "selfstore") {
4609
+ register(prefix, {
4610
+ connect: SelfstoreConnectElement,
4611
+ status: SelfstoreStatusElement,
4612
+ destination: SelfstoreDestinationElement
4613
+ });
4614
+ }
4615
+ function defineStorage(prefix = "selfstore") {
4616
+ defineGate(prefix);
4617
+ defineDestination(prefix);
4618
+ register(prefix, { storage: SelfstoreStorageElement });
4619
+ }
4620
+ function defineAccount(prefix = "selfstore") {
4621
+ register(prefix, {
4622
+ status: SelfstoreStatusElement,
4623
+ account: SelfstoreAccountElement
4624
+ });
4625
+ }
4532
4626
  function defineSelfstoreWidgets(prefix = "selfstore") {
4533
- const define = (name, ctor) => {
4534
- if (!customElements.get(name)) customElements.define(name, ctor);
4535
- };
4536
- define(`${prefix}-connect`, SelfstoreConnectElement);
4537
- define(`${prefix}-share`, SelfstoreShareElement);
4538
- define(`${prefix}-join`, SelfstoreJoinElement);
4539
- define(`${prefix}-status`, SelfstoreStatusElement);
4540
- define(`${prefix}-backups`, SelfstoreBackupsElement);
4541
- define(`${prefix}-gate`, SelfstoreGateElement);
4542
- define(`${prefix}-destination`, SelfstoreDestinationElement);
4543
- define(`${prefix}-storage`, SelfstoreStorageElement);
4544
- define(`${prefix}-account`, SelfstoreAccountElement);
4627
+ register(prefix, {
4628
+ connect: SelfstoreConnectElement,
4629
+ share: SelfstoreShareElement,
4630
+ join: SelfstoreJoinElement,
4631
+ status: SelfstoreStatusElement,
4632
+ backups: SelfstoreBackupsElement,
4633
+ gate: SelfstoreGateElement,
4634
+ destination: SelfstoreDestinationElement,
4635
+ storage: SelfstoreStorageElement,
4636
+ account: SelfstoreAccountElement
4637
+ });
4545
4638
  }
4546
4639
 
4547
- export { FlowWidget, SelfstoreAccountElement, SelfstoreBackupsElement, SelfstoreConnectElement, SelfstoreDestinationElement, SelfstoreGateElement, SelfstoreJoinElement, SelfstoreShareElement, SelfstoreStatusElement, SelfstoreStorageElement, defaultIcons, defineSelfstoreWidgets };
4640
+ export { FlowWidget, SelfstoreAccountElement, SelfstoreBackupsElement, SelfstoreConnectElement, SelfstoreDestinationElement, SelfstoreGateElement, SelfstoreJoinElement, SelfstoreShareElement, SelfstoreStatusElement, SelfstoreStorageElement, defaultIcons, defineAccount, defineBackups, defineConnect, defineDestination, defineGate, defineJoin, defineSelfstoreWidgets, defineShare, defineStatus, defineStorage };
4548
4641
  //# sourceMappingURL=widgets.js.map
4549
4642
  //# sourceMappingURL=widgets.js.map