selfstore 1.8.10 → 1.8.11

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
@@ -162,7 +162,7 @@ too, as subpaths of the same install:
162
162
  |---|---|---|
163
163
  | `selfstore` | the simple store + backup files | almost always: start here |
164
164
  | `selfstore/flows` | the user journeys (connect a destination, share panel, join an invitation) as headless, tested state machines | you are building the connect/share/join UI and want the ordering and failure rules - one popup per gesture, password proven before attach, merge by default - already right |
165
- | `selfstore/widgets` | the same journeys as drop-in web components (`<selfstore-connect>`, `<selfstore-gate>`, `<selfstore-destination>`, `<selfstore-share>`, `<selfstore-join>`) - framework-free, themable via CSS custom properties and `::part()`, reworded/localized via a `labels` map | you want the screens ready-made and your app's look on top |
165
+ | `selfstore/widgets` | the same journeys as drop-in web components (`<selfstore-storage>` for the whole journey in one tag, or `<selfstore-connect>`, `<selfstore-gate>`, `<selfstore-destination>`, `<selfstore-account>`, `<selfstore-share>`, `<selfstore-join>` on their own) - framework-free, themable via CSS custom properties and `::part()`, reworded/localized via a `labels` map | you want the screens ready-made and your app's look on top |
166
166
  | `selfstore/advanced` | the pull-model store (`createLocalStore`), custom `BackupTarget`s, caches, headless status derivation, functional codec | your state lives in its own reactive model (Svelte runes, Redux), or you are writing a destination (S3, your KV...) |
167
167
  | `selfstore/groups` | passwordless group encryption: per-member identities, sealed envelopes, signed membership manifests | several PEOPLE share one encrypted store without a shared password ([PEERS.md](./PEERS.md)) |
168
168
  | `selfstore/sync` | the bare merge engine (HLC + per-collection strategies, no CRDT runtime) | you only want the algorithm inside your own persistence ([SYNC docs in SPEC.md](./SPEC.md)) |
package/dist/widgets.d.ts CHANGED
@@ -31,10 +31,13 @@ declare abstract class FlowWidget extends HTMLElement {
31
31
  /** Partial override map, merged over the EN defaults (also the i18n hook). */
32
32
  get labels(): WidgetLabels;
33
33
  set labels(map: WidgetLabels);
34
- /** The shipped translation for the page's language, if the widget has one.
35
- * An explicit `lang` on the element (or on any ancestor) wins over the
36
- * document's, which wins over the browser's, so a host that already sets
37
- * `<html lang>` gets translated copy without writing a single label. */
34
+ /** The language this widget speaks. An explicit `lang` on the element (or on
35
+ * any ancestor) wins over the document's, which wins over the browser's, so
36
+ * a host that already sets `<html lang>` gets translated copy without
37
+ * writing a single label. Also what to hand `Intl` when a widget formats a
38
+ * date or a duration itself. */
39
+ protected langTag(): string;
40
+ /** The shipped translation for the page's language, if the widget has one. */
38
41
  private localized;
39
42
  /**
40
43
  * The copy for a key, with `{placeholders}` filled in.
@@ -57,7 +60,33 @@ declare abstract class FlowWidget extends HTMLElement {
57
60
  /** Hands back whatever the host set before this class existed, then the
58
61
  * subclass reads its attributes and wires itself. Subclasses override this
59
62
  * and call `super.connectedCallback()` FIRST, for that reason. */
63
+ /**
64
+ * What the HOST decided before this element could hear it.
65
+ *
66
+ * Assigning a property to an element that has not upgraded yet is what every
67
+ * framework does - the widget bundle is loaded lazily, the assignment is
68
+ * not - and `upgradeOwnProperties` replays those assignments through the
69
+ * real setters. Then reading the same knob back from the markup would undo
70
+ * them: an attribute is a DEFAULT written by the page, a property is a
71
+ * decision taken by the app, and the decision has to win. A widget reads its
72
+ * attributes through this set.
73
+ */
74
+ protected assigned: Set<string>;
60
75
  connectedCallback(): void;
76
+ /**
77
+ * An attribute the host has NOT already decided in code, or null.
78
+ *
79
+ * Two ways it can have decided, and both have to be caught. It replayed
80
+ * through `assigned` on connect - or it has not been replayed yet, and its
81
+ * value is sitting on the element as an own property shadowing this very
82
+ * accessor. That second case is the one that bit: on upgrade the browser
83
+ * fires attributeChangedCallback BEFORE connectedCallback, so a widget
84
+ * writing the attribute through its own setter wrote into the shadowing own
85
+ * property instead - overwriting the decision it was about to replay.
86
+ */
87
+ protected attr(name: string): string | null;
88
+ /** The same, as a boolean: absent is null, anything but "false" is true. */
89
+ protected flag(name: string): boolean | null;
61
90
  protected emit(name: string, detail?: unknown): void;
62
91
  /** Rebuild the body, keeping the focused input's value and focus across the
63
92
  * rebuild (inputs carry data-keep so typing survives a snapshot change). */
@@ -523,7 +552,7 @@ declare class SelfstoreGateElement extends FlowWidget {
523
552
  * `flow` included). Null while the gate is shut. */
524
553
  get connect(): SelfstoreConnectElement | null;
525
554
  constructor();
526
- attributeChangedCallback(name: string, _old: string | null, value: string | null): void;
555
+ attributeChangedCallback(name: string): void;
527
556
  connectedCallback(): void;
528
557
  private host;
529
558
  private wire;
@@ -673,7 +702,7 @@ declare class SelfstoreStorageElement extends FlowWidget {
673
702
  /** Which destination the first-run screen badges as recommended. */
674
703
  get recommended(): ConnectKind | null;
675
704
  set recommended(v: ConnectKind | null);
676
- attributeChangedCallback(name: string, _old: string | null, value: string | null): void;
705
+ attributeChangedCallback(name: string): void;
677
706
  connectedCallback(): void;
678
707
  private host;
679
708
  /** What the store offers, unless the host said otherwise. */
@@ -681,10 +710,101 @@ declare class SelfstoreStorageElement extends FlowWidget {
681
710
  protected view(into: HTMLElement): void;
682
711
  }
683
712
 
713
+ /**
714
+ * <selfstore-account>: the storage control in an app's chrome.
715
+ *
716
+ * document.querySelector('selfstore-account').store = store;
717
+ *
718
+ * A trigger that states where the data is going, and a short menu that answers
719
+ * the two questions a header should answer: WHO holds my backup and when was
720
+ * it last written, and how do I change my mind.
721
+ *
722
+ * Why it is short. The panel (<selfstore-destination>) offers four gestures,
723
+ * which is right for a settings page and wrong for a menu: a header that opens
724
+ * onto "export a copy / restore a copy / change backup / stop saving here"
725
+ * asks the user to arbitrate between four irreversible-looking words before
726
+ * they know what any of them does. So this element keeps exactly two - go to
727
+ * the settings, where the panel lives, or change backup - and hands the rest
728
+ * to the page the host already has.
729
+ *
730
+ * "Change backup" detaches, and stops there. It does not run a connect journey
731
+ * of its own: an app that mounts <selfstore-gate> (or <selfstore-storage>)
732
+ * already has the first-run screen, and a store with no destination is exactly
733
+ * what that screen is for. One journey, reached the same way whether it is the
734
+ * first day or a change of mind.
735
+ */
736
+
737
+ declare class SelfstoreAccountElement extends FlowWidget {
738
+ #private;
739
+ protected defaults(): WidgetLabels;
740
+ protected packs(): Record<string, WidgetLabels>;
741
+ constructor();
742
+ /** The simple store (anything exposing `flowHost`), or a hand-built FlowHost.
743
+ * A simple store also answers `account` on its own, so nothing else is
744
+ * needed to name who holds the backup. */
745
+ get store(): StoreLike | null;
746
+ set store(v: StoreLike | null);
747
+ get account(): string | null;
748
+ set account(v: string | null);
749
+ /** Optional glyph per destination kind, same contract as the connect cards. */
750
+ get icons(): Partial<Record<ConnectKind, string>>;
751
+ set icons(v: Partial<Record<ConnectKind, string>> | null);
752
+ /** Veto on changing backup, which leaves the app with no destination until
753
+ * the user picks one. Returns false (or throws) to stop. */
754
+ get confirmAction(): ((a: DestinationAction) => boolean | Promise<boolean>) | null;
755
+ set confirmAction(fn: ((a: DestinationAction) => boolean | Promise<boolean>) | null);
756
+ /** Whether the menu is on screen. Settable, so a host can close it from its
757
+ * own router after the settings item navigated away. */
758
+ get open(): boolean;
759
+ set open(v: boolean);
760
+ connectedCallback(): void;
761
+ disconnectedCallback(): void;
762
+ /** While the menu is open: a clock for the relative time, and the two ways
763
+ * out that make it a menu rather than a page - a click anywhere else, and
764
+ * Escape. `pointerdown` and not `click`, so the gesture that closes it does
765
+ * not also land on whatever was under the menu. Shadow DOM retargets the
766
+ * event, so what is asked is the composed path, never `e.target`. */
767
+ private watch;
768
+ /** The destination's name. An unknown kind (a host's own target) has no
769
+ * shipped name: its own label is a better answer than the raw key. */
770
+ private named;
771
+ /** "just now", "3 minutes ago", "yesterday" - in the page's language, from
772
+ * Intl rather than from five label keys per language. */
773
+ private when;
774
+ /**
775
+ * The one line under the account. A plain "saved" is the only state this
776
+ * element words itself, because it is the only one with nothing to do about
777
+ * it - and the only one where WHEN is the whole information. Everything else
778
+ * (reconnect, unlock, changes to download) belongs to <selfstore-status>,
779
+ * which owns both the wording and the button that resolves it.
780
+ */
781
+ private line;
782
+ /** Ask for the settings. The host owns the route, so this only says that it
783
+ * was asked - and closes, because a menu that stays open behind a page
784
+ * transition reads as a failed click. */
785
+ private settings;
786
+ /** Change backup: detach, and let the first-run screen take it from there.
787
+ * The data stays; only the destination is let go. */
788
+ private change;
789
+ private card;
790
+ protected view(into: HTMLElement): void;
791
+ /**
792
+ * Which side the menu hangs from.
793
+ *
794
+ * A header control is usually at the right edge, so the menu hangs right -
795
+ * and the moment the header wraps on a narrow window, that same control sits
796
+ * at the LEFT edge and the menu hangs off the screen. Measured rather than
797
+ * assumed: it hangs left when there is room to the right, and right
798
+ * otherwise, which lands correctly at both edges without the host declaring
799
+ * where it put the control.
800
+ */
801
+ private anchor;
802
+ }
803
+
684
804
  /** Register the elements as <PREFIX-connect>, <PREFIX-share>, <PREFIX-join>,
685
805
  * <PREFIX-status>, <PREFIX-backups>, <PREFIX-gate> and
686
806
  * <PREFIX-destination> (default prefix 'selfstore'). Safe to call twice;
687
807
  * throws in environments without custom elements (browser code only). */
688
808
  declare function defineSelfstoreWidgets(prefix?: string): void;
689
809
 
690
- export { type BackupsAction, type DestinationAction, FlowWidget, SelfstoreBackupsElement, SelfstoreConnectElement, SelfstoreDestinationElement, SelfstoreGateElement, SelfstoreJoinElement, SelfstoreShareElement, SelfstoreStatusElement, SelfstoreStorageElement, type ShareAction, type WebdavPreset, type WidgetLabels, defineSelfstoreWidgets };
810
+ export { type BackupsAction, type DestinationAction, FlowWidget, SelfstoreAccountElement, SelfstoreBackupsElement, SelfstoreConnectElement, SelfstoreDestinationElement, SelfstoreGateElement, SelfstoreJoinElement, SelfstoreShareElement, SelfstoreStatusElement, SelfstoreStorageElement, type ShareAction, type WebdavPreset, type WidgetLabels, defineSelfstoreWidgets };