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 +1 -1
- package/dist/widgets.d.ts +127 -7
- package/dist/widgets.js +454 -44
- package/dist/widgets.js.map +1 -1
- package/package.json +1 -1
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
|
|
35
|
-
*
|
|
36
|
-
*
|
|
37
|
-
*
|
|
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
|
|
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
|
|
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 };
|