@singlebase/elements 0.1.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.
Files changed (48) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +29 -0
  3. package/dist/authui.cjs +2 -0
  4. package/dist/authui.cjs.map +1 -0
  5. package/dist/authui.d.ts +22 -0
  6. package/dist/authui.js +24 -0
  7. package/dist/authui.js.map +1 -0
  8. package/dist/controllers/auth-controller.d.ts +17 -0
  9. package/dist/controllers/event-bridge.d.ts +27 -0
  10. package/dist/controllers/settings-controller.d.ts +18 -0
  11. package/dist/display-8HEcKYR4.js +3444 -0
  12. package/dist/display-8HEcKYR4.js.map +1 -0
  13. package/dist/display-CLDNNZQy.cjs +976 -0
  14. package/dist/display-CLDNNZQy.cjs.map +1 -0
  15. package/dist/elements/account-screen.d.ts +99 -0
  16. package/dist/elements/auth-screen.d.ts +215 -0
  17. package/dist/elements/base.d.ts +69 -0
  18. package/dist/elements/buttons.d.ts +45 -0
  19. package/dist/elements/display.d.ts +51 -0
  20. package/dist/elements/form-base.d.ts +23 -0
  21. package/dist/elements/guard.d.ts +65 -0
  22. package/dist/elements/uploader.d.ts +225 -0
  23. package/dist/index.cjs +2 -0
  24. package/dist/index.cjs.map +1 -0
  25. package/dist/index.d.ts +7 -0
  26. package/dist/index.js +30 -0
  27. package/dist/index.js.map +1 -0
  28. package/dist/messages.d.ts +147 -0
  29. package/dist/singlebase-elements.min.js +7616 -0
  30. package/dist/singlebase-elements.min.js.map +1 -0
  31. package/dist/standalone.d.ts +2 -0
  32. package/dist/styles/shared.d.ts +8 -0
  33. package/dist/styles/tokens.d.ts +44 -0
  34. package/dist/upload-messages.d.ts +45 -0
  35. package/dist/uploader-D-Da1trc.js +2290 -0
  36. package/dist/uploader-D-Da1trc.js.map +1 -0
  37. package/dist/uploader-eFYKpk8b.cjs +1390 -0
  38. package/dist/uploader-eFYKpk8b.cjs.map +1 -0
  39. package/dist/uploader.cjs +2 -0
  40. package/dist/uploader.cjs.map +1 -0
  41. package/dist/uploader.d.ts +10 -0
  42. package/dist/uploader.js +9 -0
  43. package/dist/uploader.js.map +1 -0
  44. package/dist/utils/files.d.ts +38 -0
  45. package/dist/utils/inspect.d.ts +23 -0
  46. package/dist/utils/profile.d.ts +9 -0
  47. package/dist/utils/redirect.d.ts +15 -0
  48. package/package.json +76 -0
@@ -0,0 +1,225 @@
1
+ import { LitElement } from "lit";
2
+ import type { FilesUploadApi } from "@singlebase/singlebase-sdk";
3
+ /** What the uploader needs from a client: `files.upload`, and nothing else. */
4
+ export type UploaderClient = {
5
+ files: Pick<FilesUploadApi, "upload">;
6
+ };
7
+ import { type SinglebaseUploadMessages } from "../upload-messages.js";
8
+ export type UploadView = "full" | "compact" | "button";
9
+ export type UploadItemStatus = "checking" | "ready" | "uploading" | "done" | "error";
10
+ /**
11
+ * Per-format limits, keyed by extension: `{ pdf: { maxPages: 10 } }`.
12
+ *
13
+ * `maxPages` and `allowProtected` need the file's bytes read, which only
14
+ * works for `pdf`, `docx`, `pptx` and `xlsx`; the size bounds apply to any
15
+ * extension and override the element-wide ones for that kind.
16
+ */
17
+ export interface FileRule {
18
+ maxPages?: number;
19
+ maxSize?: string | number;
20
+ minSize?: string | number;
21
+ /** Set false to refuse password-protected files. Default: allowed. */
22
+ allowProtected?: boolean;
23
+ }
24
+ export type FileRules = Record<string, FileRule>;
25
+ export interface UploadItem {
26
+ /** Identity for de-duplication: name, size and mtime. */
27
+ key: string;
28
+ file: File;
29
+ /** The saved name, which the user may have edited. */
30
+ name: string;
31
+ status: UploadItemStatus;
32
+ percent: number;
33
+ error: string;
34
+ /** The stored file record, once the upload completes. */
35
+ record: unknown;
36
+ /** Pages (slides for pptx) when they could be read, else null. */
37
+ pages: number | null;
38
+ /** Whether the file is encrypted, when that could be determined. */
39
+ encrypted: boolean | null;
40
+ /** A local object URL for image thumbnails; "" for everything else. */
41
+ preview: string;
42
+ }
43
+ /**
44
+ * Every setting in one object, for configuring an element from script. Keys
45
+ * are the element's property names.
46
+ */
47
+ export interface UploaderConfig {
48
+ view: UploadView;
49
+ dropzone: boolean;
50
+ allowRename: boolean;
51
+ autoUpload: boolean;
52
+ branding: boolean;
53
+ logoUrl: string;
54
+ logoText: string;
55
+ heading: string;
56
+ description: string;
57
+ maxFiles: number;
58
+ maxSize: string | number;
59
+ minSize: string | number;
60
+ accept: string;
61
+ rules: FileRules;
62
+ bucket: string;
63
+ publicRead: boolean;
64
+ redirectUrl: string;
65
+ metadata: Record<string, unknown>;
66
+ options: Record<string, unknown>;
67
+ messages: Partial<SinglebaseUploadMessages>;
68
+ theme: "light" | "dark";
69
+ density: "comfortable" | "compact";
70
+ onComplete: SinglebaseUploader["onComplete"];
71
+ onError: SinglebaseUploader["onError"];
72
+ }
73
+ /**
74
+ * A file picker that uploads straight to storage.
75
+ *
76
+ * <singlebase-uploader></singlebase-uploader>
77
+ * <singlebase-uploader view="compact" accept=".pdf,image/*"></singlebase-uploader>
78
+ * <singlebase-uploader view="button" max-files="1"></singlebase-uploader>
79
+ *
80
+ * It owns the staging list — picking, renaming, removing, validating, and the
81
+ * progress of each file — and nothing else. When the batch finishes it emits
82
+ * the stored records and stops; what the application does with them (attach
83
+ * them to a record, show a gallery, save an avatar) is the application's
84
+ * decision, not the widget's.
85
+ *
86
+ * Failures are per file. One rejected upload leaves the rest completed and
87
+ * offers that row a retry, mirroring the SDK's own behaviour.
88
+ */
89
+ export declare class SinglebaseUploader extends LitElement {
90
+ static styles: import("lit").CSSResult[];
91
+ /** An explicit client. Omit it and the page's SinglebaseClient() is used. */
92
+ accessor client: UploaderClient | null;
93
+ accessor messages: Partial<SinglebaseUploadMessages>;
94
+ accessor theme: "light" | "dark" | undefined;
95
+ accessor density: "comfortable" | "compact" | undefined;
96
+ /**
97
+ * `full` is the card with a dropzone and a reviewable list, `compact` the
98
+ * one-line attachments row, `button` a single control that uploads as soon
99
+ * as a file is chosen.
100
+ */
101
+ accessor view: UploadView;
102
+ /** Show the drop target. Off leaves the picker button on its own. */
103
+ accessor dropzone: boolean;
104
+ /** Let the user edit the saved filename before uploading. */
105
+ accessor allowRename: boolean;
106
+ /** Upload as soon as files are picked, with no review step. */
107
+ accessor autoUpload: boolean;
108
+ /** The "Files by Singlebase" credit. A plain link — it makes no request. */
109
+ accessor branding: boolean;
110
+ accessor logoUrl: string;
111
+ accessor logoText: string;
112
+ accessor heading: string;
113
+ accessor description: string;
114
+ accessor maxFiles: number;
115
+ /** Bytes, or a human size like "25MB". 0 or "" means no limit. */
116
+ accessor maxSize: string | number;
117
+ accessor minSize: string | number;
118
+ /** Same vocabulary as `<input type="file" accept>`. */
119
+ accessor accept: string;
120
+ /**
121
+ * Per-format limits, as JSON in markup or an object in JavaScript:
122
+ *
123
+ * rules='{"pdf":{"maxPages":10,"allowProtected":false}}'
124
+ *
125
+ * Checking pages and encryption means reading the file in the browser, so
126
+ * it is a convenience for the person picking files — never a substitute
127
+ * for the server enforcing the same limits.
128
+ */
129
+ accessor rules: FileRules;
130
+ accessor bucket: string;
131
+ /** Metadata attached to every file this element uploads. */
132
+ accessor metadata: Record<string, unknown>;
133
+ /**
134
+ * `options` sent with every file's upload request — for instance
135
+ * `{ profile_photo: true }`, which makes the upload the account's photo.
136
+ */
137
+ accessor options: Record<string, unknown>;
138
+ accessor publicRead: boolean;
139
+ /** Where to go once every file has uploaded. Same-origin only. */
140
+ accessor redirectUrl: string;
141
+ /** Callback forms of the two events, for frameworks that prefer props. */
142
+ accessor onComplete: ((detail: {
143
+ completed: UploadItem[];
144
+ failed: UploadItem[];
145
+ }) => void) | null;
146
+ accessor onError: ((detail: {
147
+ message: string;
148
+ }) => void) | null;
149
+ private accessor items;
150
+ private accessor notice;
151
+ private accessor busy;
152
+ private accessor dragging;
153
+ private accessor editing;
154
+ get msg(): SinglebaseUploadMessages;
155
+ /** An explicit `.client`, else the page default. */
156
+ get resolvedClient(): UploaderClient | null;
157
+ /** The staging list, for host code that wants to inspect or persist it. */
158
+ get files(): readonly UploadItem[];
159
+ /** Overall progress across the current batch, 0–100. */
160
+ get percent(): number;
161
+ /** Opens the file picker. */
162
+ open(): void;
163
+ /**
164
+ * Applies several settings at once:
165
+ *
166
+ * document.getElementById("docs").config = { maxFiles: 5, metadata: { folder: "q3" } };
167
+ *
168
+ * Unknown keys are ignored. Reading it returns the current settings.
169
+ */
170
+ set config(value: Partial<UploaderConfig>);
171
+ get config(): Partial<UploaderConfig>;
172
+ /** Drops every staged file and any notice. */
173
+ clear(): void;
174
+ disconnectedCallback(): void;
175
+ /** Uploads everything staged. Rows that already succeeded are left alone. */
176
+ upload(): Promise<void>;
177
+ /** The rule for this filename's extension, if the host set one. */
178
+ private ruleFor;
179
+ private add;
180
+ private needsInspection;
181
+ /**
182
+ * Reads the file and applies the rule. A fact the reader could not
183
+ * determine is not grounds for rejection — an unreadable page count means
184
+ * the page rule simply doesn't apply to that file.
185
+ */
186
+ private inspect;
187
+ /** Drops one staged file. Named for the row action, not Element.remove(). */
188
+ private removeItem;
189
+ private commitRename;
190
+ private fail;
191
+ private emit;
192
+ private redirect;
193
+ private onPick;
194
+ private onDrop;
195
+ private onDragOver;
196
+ private onDragLeave;
197
+ private get canAddMore();
198
+ /** True while any staged file is still being read. */
199
+ private get checking();
200
+ private get pendingCount();
201
+ private get hint();
202
+ private renderInput;
203
+ private renderLogo;
204
+ private renderBranding;
205
+ private renderNotice;
206
+ private renderCount;
207
+ private renderStatus;
208
+ private renderRow;
209
+ private renderRows;
210
+ private renderDropzone;
211
+ private renderUploadCta;
212
+ /**
213
+ * The whole card is the drop surface. Once files are staged the big zone is
214
+ * replaced by the "add more" control, and a drop should still land.
215
+ */
216
+ private renderFull;
217
+ private renderCompact;
218
+ private renderButton;
219
+ render(): import("lit").TemplateResult<1>;
220
+ }
221
+ declare global {
222
+ interface HTMLElementTagNameMap {
223
+ "singlebase-uploader": SinglebaseUploader;
224
+ }
225
+ }
package/dist/index.cjs ADDED
@@ -0,0 +1,2 @@
1
+ "use strict";Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});const e=require("./display-CLDNNZQy.cjs"),t=require("./uploader-eFYKpk8b.cjs"),r=require("@singlebase/core");exports.AuthController=e.AuthController;exports.SettingsController=e.SettingsController;Object.defineProperty(exports,"SinglebaseAccountScreen",{enumerable:!0,get:()=>e.SinglebaseAccountScreen});Object.defineProperty(exports,"SinglebaseAuthButtons",{enumerable:!0,get:()=>e.SinglebaseAuthButtons});Object.defineProperty(exports,"SinglebaseAuthDisplay",{enumerable:!0,get:()=>e.SinglebaseAuthDisplay});Object.defineProperty(exports,"SinglebaseAuthGuard",{enumerable:!0,get:()=>e.SinglebaseAuthGuard});Object.defineProperty(exports,"SinglebaseAuthScreen",{enumerable:!0,get:()=>e.SinglebaseAuthScreen});exports.defaultMessages=e.defaultMessages;exports.fullNameOf=e.fullNameOf;exports.initialsOf=e.initialsOf;exports.isGuestScreen=e.isGuestScreen;exports.isProtectedScreen=e.isProtectedScreen;exports.isScreen=e.isScreen;exports.resolveMessages=e.resolveMessages;Object.defineProperty(exports,"SinglebaseUploader",{enumerable:!0,get:()=>t.SinglebaseUploader});exports.TOKEN_DEFAULTS=t.TOKEN_DEFAULTS;exports.defaultUploadMessages=t.defaultUploadMessages;exports.inspectFile=t.inspectFile;exports.isInspectable=t.isInspectable;exports.resolveRedirectTarget=t.resolveRedirectTarget;exports.resolveUploadMessages=t.resolveUploadMessages;Object.defineProperty(exports,"OPERATORS",{enumerable:!0,get:()=>r.OPERATORS});Object.defineProperty(exports,"matchesPredicate",{enumerable:!0,get:()=>r.matchesPredicate});Object.defineProperty(exports,"validatePredicate",{enumerable:!0,get:()=>r.validatePredicate});
2
+ //# sourceMappingURL=index.cjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.cjs","sources":[],"sourcesContent":[],"names":[],"mappings":""}
@@ -0,0 +1,7 @@
1
+ /**
2
+ * `@singlebase/elements` — every element. Import `./authui` or `./uploader`
3
+ * instead to take only one family.
4
+ */
5
+ export * from "./authui.js";
6
+ export * from "./uploader.js";
7
+ export { TOKEN_DEFAULTS } from "./styles/tokens.js";
package/dist/index.js ADDED
@@ -0,0 +1,30 @@
1
+ import { A as a, S as t, a as r, b as l, c as i, d as n, e as o, f as S, g as c, i as d, h as g, j as u, k as b, r as f } from "./display-8HEcKYR4.js";
2
+ import { S as A, T as h, d as m, i as O, a as T, r as v, b as M } from "./uploader-D-Da1trc.js";
3
+ import { OPERATORS as U, matchesPredicate as x, validatePredicate as E } from "@singlebase/core";
4
+ export {
5
+ a as AuthController,
6
+ U as OPERATORS,
7
+ t as SettingsController,
8
+ r as SinglebaseAccountScreen,
9
+ l as SinglebaseAuthButtons,
10
+ i as SinglebaseAuthDisplay,
11
+ n as SinglebaseAuthGuard,
12
+ o as SinglebaseAuthScreen,
13
+ A as SinglebaseUploader,
14
+ h as TOKEN_DEFAULTS,
15
+ S as defaultMessages,
16
+ m as defaultUploadMessages,
17
+ c as fullNameOf,
18
+ d as initialsOf,
19
+ O as inspectFile,
20
+ g as isGuestScreen,
21
+ T as isInspectable,
22
+ u as isProtectedScreen,
23
+ b as isScreen,
24
+ x as matchesPredicate,
25
+ f as resolveMessages,
26
+ v as resolveRedirectTarget,
27
+ M as resolveUploadMessages,
28
+ E as validatePredicate
29
+ };
30
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sources":[],"sourcesContent":[],"names":[],"mappings":";;;"}
@@ -0,0 +1,147 @@
1
+ /**
2
+ * Default UI copy, taken verbatim from the design mock's renderVals()
3
+ * (titles/subs/ctas maps and inline strings in project/AuthWidget.dc.html).
4
+ * Every element accepts a .messages property with a partial override of
5
+ * this shape — spec: "configurable labels and messages without changing flow
6
+ * logic". This is deliberately a flat string bag rather than a locale-file
7
+ * system; hosts needing full i18n supply one populated object per language.
8
+ */
9
+ export interface SinglebaseAuthMessages {
10
+ signInTitle: string;
11
+ signUpTitle: string;
12
+ forgotTitle: string;
13
+ verifyTitle: string;
14
+ otpTitle: string;
15
+ newPassTitle: string;
16
+ inviteTitle: string;
17
+ signInSubEmailAndOauth: string;
18
+ signInSubEmailOnly: string;
19
+ signInSubOauthOnly: string;
20
+ signUpSub: string;
21
+ forgotSub: string;
22
+ otpSub: string;
23
+ inviteSub: string;
24
+ signInCta: string;
25
+ signUpCta: string;
26
+ forgotCta: string;
27
+ verifyCta: string;
28
+ otpCta: string;
29
+ newPassCta: string;
30
+ inviteCta: string;
31
+ continueCta: string;
32
+ backCta: string;
33
+ emailMethodTitle: string;
34
+ emailMethodTitleSignUp: string;
35
+ emailMethodMeta: string;
36
+ emailMethodMetaSignUp: string;
37
+ emailMethodMetaOtp: string;
38
+ oauthMethodTitle: string;
39
+ oauthMethodMeta: string;
40
+ fullNameLabel: string;
41
+ fullNamePlaceholder: string;
42
+ emailLabel: string;
43
+ emailPlaceholder: string;
44
+ passwordLabel: string;
45
+ passwordPlaceholder: string;
46
+ newPasswordLabel: string;
47
+ newPasswordPlaceholder: string;
48
+ confirmPasswordLabel: string;
49
+ confirmPasswordPlaceholder: string;
50
+ currentPasswordLabel: string;
51
+ firstNameLabel: string;
52
+ firstNamePlaceholder: string;
53
+ lastNameLabel: string;
54
+ lastNamePlaceholder: string;
55
+ phoneLabel: string;
56
+ phonePlaceholder: string;
57
+ invitedEmailLabel: string;
58
+ forgotLink: string;
59
+ otpInsteadLink: string;
60
+ footTextSignIn: string;
61
+ footActionSignIn: string;
62
+ footTextSignUp: string;
63
+ footActionSignUp: string;
64
+ resendQuestion: string;
65
+ resendCta: string;
66
+ oauthPrimaryLabel: string;
67
+ oauthContinueWith: string;
68
+ blockedTitleDisabled: string;
69
+ blockedTitleUnavailable: string;
70
+ blockedBodyDisabled: string;
71
+ blockedBodyUnavailable: string;
72
+ blockedHint: string;
73
+ signOutCta: string;
74
+ addPhotoLink: string;
75
+ changePhotoLink: string;
76
+ photoUploading: string;
77
+ photoUpdated: string;
78
+ editingLabel: string;
79
+ uploadPhotoCta: string;
80
+ replacePhotoCta: string;
81
+ photoHint: string;
82
+ doneCta: string;
83
+ cancelCta: string;
84
+ editAccountCta: string;
85
+ saveChangesCta: string;
86
+ emailChangeHint: string;
87
+ passwordSectionTitle: string;
88
+ passwordChangedHint: string;
89
+ changePasswordCta: string;
90
+ updatePasswordCta: string;
91
+ twoFaTitle: string;
92
+ twoFaHintOff: string;
93
+ twoFaHintOn: string;
94
+ twoFaScanHint: string;
95
+ connectedTitle: string;
96
+ connectedHint: string;
97
+ addAnotherLabel: string;
98
+ disconnectCta: string;
99
+ notConnectedLabel: string;
100
+ deleteAccountCta: string;
101
+ deleteAccountConfirmCta: string;
102
+ deletePanelBody: string;
103
+ deleteConfirmLabel: string;
104
+ deleteConfirmPlaceholder: string;
105
+ savedNote: string;
106
+ passwordUpdatedNote: string;
107
+ changeEmailTitle: string;
108
+ newEmailLabel: string;
109
+ changeEmailCta: string;
110
+ changeUsernameTitle: string;
111
+ newUsernameLabel: string;
112
+ changeUsernameCta: string;
113
+ genericErrorMessage: string;
114
+ rateLimitedMessage: string;
115
+ codeSentNeutral: string;
116
+ invalidEmailError: string;
117
+ requiredError: string;
118
+ passwordMinError: string;
119
+ passwordMatchError: string;
120
+ codeIncompleteError: string;
121
+ invalidPhoneError: string;
122
+ notYetSupported: string;
123
+ alreadySignedInTitle: string;
124
+ alreadySignedInSub: string;
125
+ alreadySignedInSubPrefix: string;
126
+ continueHint: string;
127
+ consentPrefix: string;
128
+ consentJoin: string;
129
+ termsLabel: string;
130
+ privacyLabel: string;
131
+ emailUnchangedError: string;
132
+ emailUpdatedNote: string;
133
+ changeEmailCtaShort: string;
134
+ changeEmailHint: string;
135
+ changeEmailConfirmHint: string;
136
+ changeEmailElsewhereHint: string;
137
+ confirmChangeCta: string;
138
+ codeLabel: string;
139
+ /** The credit under the card. A brand name — translate only the "Auth by". */
140
+ brandingLabel: string;
141
+ linkRequiresSignIn: string;
142
+ oauthCallbackTitle: string;
143
+ oauthCallbackSub: string;
144
+ oauthDenied: string;
145
+ }
146
+ export declare const defaultMessages: SinglebaseAuthMessages;
147
+ export declare function resolveMessages(overrides?: Partial<SinglebaseAuthMessages>): SinglebaseAuthMessages;