@mevdragon/vidfarm-devcli 0.17.0 → 0.18.1
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/.agents/skills/vidfarm-media/SKILL.md +43 -6
- package/SKILL.director.md +37 -23
- package/SKILL.platform.md +6 -6
- package/demo/dist/app.js +69 -69
- package/demo/dist/favicon.ico +0 -0
- package/dist/src/app.js +1832 -213
- package/dist/src/cli.js +238 -17
- package/dist/src/devcli/clip-store.js +29 -2
- package/dist/src/devcli/clips.js +116 -73
- package/dist/src/devcli/composition-edit.js +262 -0
- package/dist/src/devcli/timeline-edit.js +283 -0
- package/dist/src/editor-chat.js +29 -6
- package/dist/src/frontend/discover-client.js +130 -0
- package/dist/src/frontend/discover-store.js +23 -0
- package/dist/src/frontend/file-directory.js +744 -0
- package/dist/src/frontend/template-editor-chat.js +22 -19
- package/dist/src/landing-page.js +24 -7
- package/dist/src/page-shell.js +25 -1
- package/dist/src/reskin/agency-page.js +214 -170
- package/dist/src/reskin/calendar-page.js +503 -187
- package/dist/src/reskin/chat-page.js +739 -299
- package/dist/src/reskin/discover-page.js +1450 -279
- package/dist/src/reskin/document.js +1392 -16
- package/dist/src/reskin/help-page.js +139 -100
- package/dist/src/reskin/index-page.js +1 -1
- package/dist/src/reskin/inpaint-page.js +547 -0
- package/dist/src/reskin/job-runs-page.js +355 -127
- package/dist/src/reskin/library-page.js +1188 -317
- package/dist/src/reskin/login-page.js +124 -87
- package/dist/src/reskin/pricing-page.js +197 -166
- package/dist/src/reskin/settings-page.js +566 -187
- package/dist/src/reskin/theme.js +434 -17
- package/dist/src/services/clip-curation/gemini.js +5 -0
- package/dist/src/services/clip-curation/hunt.js +79 -1
- package/dist/src/services/clip-curation/index.js +2 -1
- package/dist/src/services/clip-curation/local-agent.js +4 -3
- package/dist/src/services/clip-curation/media-select.js +85 -0
- package/dist/src/services/clip-curation/query.js +5 -1
- package/dist/src/services/clip-curation/refine.js +50 -20
- package/dist/src/services/clip-curation/scan.js +10 -3
- package/dist/src/services/clip-curation/taxonomy.js +3 -1
- package/dist/src/services/clip-curation/taxonomy.v1.json +13 -1
- package/dist/src/services/clip-records.js +14 -1
- package/dist/src/services/clip-search.js +43 -13
- package/dist/src/services/file-directory.js +114 -0
- package/dist/src/services/storage.js +24 -1
- package/dist/src/services/upstream.js +5 -5
- package/dist/src/template-editor-shell.js +16 -2
- package/package.json +1 -1
- package/public/assets/discover-client-app.js +1 -0
- package/public/assets/file-directory-app.js +2 -0
- package/public/assets/homepage-client-app.js +12 -12
- package/public/assets/page-runtime-client-app.js +24 -24
- package/src/assets/favicon.ico +0 -0
- package/src/assets/logo-vidfarm.png +0 -0
|
@@ -1,23 +1,115 @@
|
|
|
1
|
-
// /reskin/login — the auth screen ported into the farmville design system
|
|
1
|
+
// /reskin/login — the auth screen ported into the farmville design system,
|
|
2
|
+
// now MIGRATED to the REAL production auth (no more fake password-only form).
|
|
2
3
|
//
|
|
3
4
|
// Bare chrome (no shared top nav / footer): an auth screen owns its whole
|
|
4
5
|
// canvas, so we render just the body over a warm sunny background. A two-column
|
|
5
6
|
// composition — a sunlit brand/marketing panel on the left, a floating white
|
|
6
7
|
// auth card on the right — collapses to a single centered card on small screens.
|
|
7
8
|
//
|
|
8
|
-
//
|
|
9
|
-
//
|
|
10
|
-
//
|
|
11
|
-
// the
|
|
12
|
-
// password
|
|
13
|
-
//
|
|
14
|
-
|
|
15
|
-
//
|
|
16
|
-
|
|
17
|
-
|
|
9
|
+
// This accepts the SAME input object the live /login route already builds (via
|
|
10
|
+
// `Parameters<typeof renderLoginPage>[0]`), so the route wiring is just "call
|
|
11
|
+
// this instead of the legacy renderer". Every form posts to the REAL login
|
|
12
|
+
// endpoints with the exact field names the live login uses:
|
|
13
|
+
// • password: POST ${routePrefix}/password?mode=password {email,password}
|
|
14
|
+
// • OTP request: POST ${routePrefix}/otp/request?mode=otp {email}
|
|
15
|
+
// • OTP verify: POST ${routePrefix}/otp/verify?mode=otp {email(hidden),code,name?}
|
|
16
|
+
// routePrefix defaults to "/login" but is honored from the input (e.g. the
|
|
17
|
+
// agency-client login uses "/agency-client-login"). On success the real
|
|
18
|
+
// endpoints own the redirect (post-login return path) — we never fake it.
|
|
19
|
+
//
|
|
20
|
+
// The segmented control at the top switches between the two REAL modes
|
|
21
|
+
// (Email code = otp, Password) via honest ?mode= links, so it mirrors the
|
|
22
|
+
// live login's mode handling exactly. Design stays farmville; NO emoji.
|
|
23
|
+
import { reskinDocument, rkEscape } from "./document.js";
|
|
18
24
|
const EYE = `<svg width="18" height="18" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M2 12s3.5-7 10-7 10 7 10 7-3.5 7-10 7-10-7-10-7Z"/><circle cx="12" cy="12" r="3"/></svg>`;
|
|
19
25
|
const MAIL = `<svg width="18" height="18" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.8" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"><rect x="3" y="5" width="18" height="14" rx="3"/><path d="m3.5 7 8.5 6 8.5-6"/></svg>`;
|
|
20
|
-
|
|
26
|
+
const LOCK = `<svg width="18" height="18" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.8" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"><rect x="4" y="10" width="16" height="10" rx="2.5"/><path d="M8 10V7a4 4 0 0 1 8 0v3"/></svg>`;
|
|
27
|
+
export function renderReskinLogin(input = {}) {
|
|
28
|
+
// Mirror the live renderer's normalization exactly.
|
|
29
|
+
const mode = input.mode === "password" ? "password" : "otp";
|
|
30
|
+
const routePrefix = input.routePrefix || "/login";
|
|
31
|
+
const rp = rkEscape(routePrefix);
|
|
32
|
+
const email = rkEscape(input.email ?? "");
|
|
33
|
+
const otpSent = Boolean(input.otpSent);
|
|
34
|
+
// REAL endpoints (same as src/account-pages-legacy.ts → renderLoginPage).
|
|
35
|
+
const PASSWORD_ACTION = `${rp}/password?mode=password`;
|
|
36
|
+
const OTP_REQUEST_ACTION = `${rp}/otp/request?mode=otp`;
|
|
37
|
+
const OTP_VERIFY_ACTION = `${rp}/otp/verify?mode=otp`;
|
|
38
|
+
const OTP_HREF = `${rp}?mode=otp`;
|
|
39
|
+
const PASSWORD_HREF = `${rp}?mode=password`;
|
|
40
|
+
const message = input.message
|
|
41
|
+
? `<div class="rk-notice rk-notice-ok rk-login-flash">${rkEscape(input.message)}</div>`
|
|
42
|
+
: "";
|
|
43
|
+
const error = input.error
|
|
44
|
+
? `<div class="rk-notice rk-notice-err rk-login-flash">${rkEscape(input.error)}</div>`
|
|
45
|
+
: "";
|
|
46
|
+
// ── segmented mode control (real ?mode= links) ──────────────────────────
|
|
47
|
+
// Hidden while verifying a code (mid-flow) — there we show "Change email".
|
|
48
|
+
const seg = otpSent
|
|
49
|
+
? ""
|
|
50
|
+
: `<div class="rk-login-seg" role="tablist" aria-label="Choose a sign-in method">
|
|
51
|
+
<span class="rk-login-seg-thumb${mode === "password" ? " is-right" : ""}"></span>
|
|
52
|
+
<a class="rk-login-seg-btn${mode === "otp" ? " is-active" : ""}" href="${OTP_HREF}" role="tab" aria-selected="${mode === "otp" ? "true" : "false"}">Email code</a>
|
|
53
|
+
<a class="rk-login-seg-btn${mode === "password" ? " is-active" : ""}" href="${PASSWORD_HREF}" role="tab" aria-selected="${mode === "password" ? "true" : "false"}">Password</a>
|
|
54
|
+
</div>`;
|
|
55
|
+
// ── header copy per state ───────────────────────────────────────────────
|
|
56
|
+
const head = mode === "password"
|
|
57
|
+
? { title: "Welcome back", sub: "Log in with your email and password." }
|
|
58
|
+
: otpSent
|
|
59
|
+
? { title: "Check your email", sub: `Enter the 6-digit code we sent${input.email ? ` to ${email}` : ""}.` }
|
|
60
|
+
: { title: "Sign in with a code", sub: "We'll email you a 6-digit code — no password to remember." };
|
|
61
|
+
// ── the auth form (three honest states) ─────────────────────────────────
|
|
62
|
+
let authPane;
|
|
63
|
+
if (mode === "password") {
|
|
64
|
+
authPane = `
|
|
65
|
+
<form class="rk-stack rk-login-form" method="post" action="${PASSWORD_ACTION}">
|
|
66
|
+
<div class="rk-field">
|
|
67
|
+
<label class="rk-label" for="rk-login-email">Email</label>
|
|
68
|
+
<input class="rk-input" id="rk-login-email" type="email" name="email" value="${email}" placeholder="you@studio.co" autocomplete="email" required autofocus />
|
|
69
|
+
</div>
|
|
70
|
+
<div class="rk-field">
|
|
71
|
+
<label class="rk-label" for="rk-login-pass">Password</label>
|
|
72
|
+
<div class="rk-input-group">
|
|
73
|
+
<input class="rk-input" id="rk-login-pass" type="password" name="password" placeholder="••••••••" autocomplete="current-password" required />
|
|
74
|
+
<button class="rk-btn rk-btn-ghost rk-btn-sm rk-login-eye" type="button" data-rk-reveal="rk-login-pass" aria-label="Show password">${EYE}</button>
|
|
75
|
+
</div>
|
|
76
|
+
</div>
|
|
77
|
+
<button class="rk-btn rk-btn-gold rk-btn-lg rk-btn-block rk-login-submit" type="submit">Log in <span class="rk-arrow">→</span></button>
|
|
78
|
+
</form>
|
|
79
|
+
|
|
80
|
+
<div class="rk-login-divider"><span>or</span></div>
|
|
81
|
+
<a class="rk-btn rk-btn-ghost rk-btn-lg rk-btn-block rk-login-alt" href="${OTP_HREF}">${MAIL} Email me a login code</a>`;
|
|
82
|
+
}
|
|
83
|
+
else if (otpSent) {
|
|
84
|
+
authPane = `
|
|
85
|
+
<form class="rk-stack rk-login-form" method="post" action="${OTP_VERIFY_ACTION}">
|
|
86
|
+
<input type="hidden" name="email" value="${email}" />
|
|
87
|
+
<div class="rk-field">
|
|
88
|
+
<label class="rk-label" for="rk-login-code">6-digit code</label>
|
|
89
|
+
<input class="rk-input rk-login-code" id="rk-login-code" name="code" inputmode="numeric" autocomplete="one-time-code" maxlength="6" pattern="[0-9]*" placeholder="000000" autofocus required />
|
|
90
|
+
</div>
|
|
91
|
+
<div class="rk-field">
|
|
92
|
+
<label class="rk-label" for="rk-login-name">Your name <span class="rk-login-optional">(optional — for new accounts)</span></label>
|
|
93
|
+
<input class="rk-input" id="rk-login-name" name="name" type="text" placeholder="Dylan Vane" autocomplete="name" />
|
|
94
|
+
</div>
|
|
95
|
+
<button class="rk-btn rk-btn-gold rk-btn-lg rk-btn-block rk-login-submit" type="submit">Verify & continue <span class="rk-arrow">→</span></button>
|
|
96
|
+
</form>
|
|
97
|
+
|
|
98
|
+
<p class="rk-login-foot"><a href="${OTP_HREF}">Use a different email</a></p>`;
|
|
99
|
+
}
|
|
100
|
+
else {
|
|
101
|
+
authPane = `
|
|
102
|
+
<form class="rk-stack rk-login-form" method="post" action="${OTP_REQUEST_ACTION}">
|
|
103
|
+
<div class="rk-field">
|
|
104
|
+
<label class="rk-label" for="rk-login-email">Email</label>
|
|
105
|
+
<input class="rk-input" id="rk-login-email" type="email" name="email" value="${email}" placeholder="you@studio.co" autocomplete="email" required autofocus />
|
|
106
|
+
</div>
|
|
107
|
+
<button class="rk-btn rk-btn-gold rk-btn-lg rk-btn-block rk-login-submit" type="submit">${MAIL} Email me a login code</button>
|
|
108
|
+
</form>
|
|
109
|
+
|
|
110
|
+
<div class="rk-login-divider"><span>or</span></div>
|
|
111
|
+
<a class="rk-btn rk-btn-ghost rk-btn-lg rk-btn-block rk-login-alt" href="${PASSWORD_HREF}">${LOCK} Use a password instead</a>`;
|
|
112
|
+
}
|
|
21
113
|
const body = `
|
|
22
114
|
<main class="rk-login">
|
|
23
115
|
<div class="rk-login-art">
|
|
@@ -26,10 +118,9 @@ export function renderReskinLogin() {
|
|
|
26
118
|
<span class="rk-login-blob rk-login-blob-b"></span>
|
|
27
119
|
<div class="rk-login-art-inner">
|
|
28
120
|
<a class="rk-brand rk-login-brand" href="/">
|
|
29
|
-
<span class="rk-brand-mark">V</span>
|
|
121
|
+
<span class="rk-brand-mark">V</span>VidFarm
|
|
30
122
|
</a>
|
|
31
123
|
<div class="rk-login-art-copy">
|
|
32
|
-
<span class="rk-badge rk-login-eyebrow">Welcome back to the farm</span>
|
|
33
124
|
<h1 class="rk-login-hed">A week of content, made in an afternoon.</h1>
|
|
34
125
|
<p class="rk-login-lede">Sign in to spin up short-form ads from your own clips — punchy hooks, UGC energy, captions that pop.</p>
|
|
35
126
|
<ul class="rk-login-feats">
|
|
@@ -51,57 +142,30 @@ export function renderReskinLogin() {
|
|
|
51
142
|
<div class="rk-login-pane">
|
|
52
143
|
<div class="rk-login-card">
|
|
53
144
|
<a class="rk-brand rk-login-card-brand" href="/">
|
|
54
|
-
<span class="rk-brand-mark">V</span>
|
|
145
|
+
<span class="rk-brand-mark">V</span>VidFarm
|
|
55
146
|
</a>
|
|
56
147
|
|
|
57
148
|
<div class="rk-login-head">
|
|
58
|
-
<h2 class="rk-login-title"
|
|
59
|
-
<p class="rk-muted"
|
|
60
|
-
</div>
|
|
61
|
-
|
|
62
|
-
<div class="rk-login-seg" role="tablist" aria-label="Log in or sign up">
|
|
63
|
-
<span class="rk-login-seg-thumb" data-rk-thumb></span>
|
|
64
|
-
<button type="button" class="rk-login-seg-btn is-active" data-rk-seg="login" aria-selected="true">Log in</button>
|
|
65
|
-
<button type="button" class="rk-login-seg-btn" data-rk-seg="signup" aria-selected="false">Sign up</button>
|
|
149
|
+
<h2 class="rk-login-title">${rkEscape(head.title)}</h2>
|
|
150
|
+
<p class="rk-muted">${head.sub}</p>
|
|
66
151
|
</div>
|
|
67
152
|
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
</div>
|
|
73
|
-
<div class="rk-field">
|
|
74
|
-
<div class="rk-login-label-row">
|
|
75
|
-
<label class="rk-label" for="rk-login-pass">Password</label>
|
|
76
|
-
<a class="rk-login-forgot" href="${OTP_HREF}" data-rk-forgot>Forgot password?</a>
|
|
77
|
-
</div>
|
|
78
|
-
<div class="rk-input-group">
|
|
79
|
-
<input class="rk-input" id="rk-login-pass" type="password" name="password" placeholder="••••••••" autocomplete="current-password" required />
|
|
80
|
-
<button class="rk-btn rk-btn-ghost rk-btn-sm rk-login-eye" type="button" data-rk-reveal="rk-login-pass" aria-label="Show password">${EYE}</button>
|
|
81
|
-
</div>
|
|
82
|
-
</div>
|
|
83
|
-
<button class="rk-btn rk-btn-gold rk-btn-lg rk-btn-block rk-login-submit" type="submit" data-rk-submit>Log in <span class="rk-arrow">→</span></button>
|
|
84
|
-
</form>
|
|
85
|
-
|
|
86
|
-
<div class="rk-login-divider"><span>or</span></div>
|
|
87
|
-
|
|
88
|
-
<a class="rk-btn rk-btn-ghost rk-btn-lg rk-btn-block rk-login-alt" href="${OTP_HREF}">${MAIL} Email me a login code</a>
|
|
89
|
-
|
|
90
|
-
<p class="rk-login-foot" data-rk-foot>
|
|
91
|
-
New to vidfarm? <a href="#" data-rk-foot-link>Start a free trial</a>
|
|
92
|
-
</p>
|
|
153
|
+
${seg}
|
|
154
|
+
${message}
|
|
155
|
+
${error}
|
|
156
|
+
${authPane}
|
|
93
157
|
</div>
|
|
94
158
|
<p class="rk-login-legal">By continuing you agree to our <a href="#">Terms</a> & <a href="#">Privacy Policy</a>.</p>
|
|
95
159
|
</div>
|
|
96
160
|
</main>`;
|
|
97
161
|
const pageCss = `
|
|
98
|
-
.rk-login{min-height:
|
|
162
|
+
.rk-login{min-height:100svh;display:grid;grid-template-columns:1.05fr .95fr;
|
|
99
163
|
background:radial-gradient(120% 90% at 100% 0%,var(--rk-gold-tint) 0%,transparent 55%),var(--rk-bg)}
|
|
100
|
-
@media(max-width:920px){.rk-login{grid-template-columns:1fr}}
|
|
164
|
+
@media(max-width:920px),(max-height:600px){.rk-login{grid-template-columns:1fr}}
|
|
101
165
|
|
|
102
166
|
/* ── left: sunlit brand / marketing panel ── */
|
|
103
167
|
.rk-login-art{position:relative;overflow:hidden;display:flex;padding:56px clamp(2rem,4vw,4rem)}
|
|
104
|
-
@media(max-width:920px){.rk-login-art{display:none}}
|
|
168
|
+
@media(max-width:920px),(max-height:600px){.rk-login-art{display:none}}
|
|
105
169
|
.rk-login-art-sky{position:absolute;inset:0;z-index:0;background:
|
|
106
170
|
radial-gradient(72% 55% at 22% 12%,rgba(255,244,214,.96),transparent 62%),
|
|
107
171
|
radial-gradient(60% 55% at 92% 96%,rgba(255,199,56,.42),transparent 60%),
|
|
@@ -139,12 +203,13 @@ export function renderReskinLogin() {
|
|
|
139
203
|
.rk-login-card{width:100%;max-width:412px;background:var(--rk-surface);border:1px solid var(--rk-border);
|
|
140
204
|
border-radius:var(--rk-r-3xl);padding:clamp(28px,3vw,40px);box-shadow:var(--rk-shadow-xl);display:grid;gap:22px}
|
|
141
205
|
.rk-login-card-brand{display:none;font-size:20px}
|
|
142
|
-
@media(max-width:920px){.rk-login-card-brand{display:inline-flex;justify-self:center}}
|
|
206
|
+
@media(max-width:920px),(max-height:600px){.rk-login-card-brand{display:inline-flex;justify-self:center}}
|
|
143
207
|
.rk-login-head{display:grid;gap:6px;text-align:center}
|
|
144
208
|
.rk-login-title{font-size:var(--rk-text-3xl);letter-spacing:-.03em}
|
|
209
|
+
.rk-login-flash{font-size:13px;padding:11px 14px}
|
|
145
210
|
|
|
146
|
-
/* segmented
|
|
147
|
-
thumb is a plain white pill with an ink label */
|
|
211
|
+
/* segmented mode control — real ?mode= links. gold is reserved for submit, so
|
|
212
|
+
the active thumb is a plain white pill with an ink label */
|
|
148
213
|
.rk-login-seg{position:relative;display:grid;grid-template-columns:1fr 1fr;gap:2px;padding:4px;
|
|
149
214
|
background:var(--rk-n-100);border:1px solid var(--rk-border);border-radius:var(--rk-r-full)}
|
|
150
215
|
.rk-login-seg-thumb{position:absolute;z-index:0;top:4px;left:4px;width:calc(50% - 4px);height:calc(100% - 8px);
|
|
@@ -153,15 +218,15 @@ export function renderReskinLogin() {
|
|
|
153
218
|
.rk-login-seg-thumb.is-right{transform:translateX(100%)}
|
|
154
219
|
.rk-login-seg-btn{position:relative;z-index:1;appearance:none;border:0;background:transparent;cursor:pointer;
|
|
155
220
|
padding:9px 12px;border-radius:var(--rk-r-full);font-family:var(--rk-font-body);font-size:14px;font-weight:600;
|
|
156
|
-
color:var(--rk-n-500);transition:color var(--rk-dur) var(--rk-ease)}
|
|
221
|
+
text-align:center;color:var(--rk-n-500);transition:color var(--rk-dur) var(--rk-ease)}
|
|
157
222
|
.rk-login-seg-btn.is-active{color:var(--rk-ink)}
|
|
158
223
|
|
|
159
224
|
.rk-login-form{gap:16px}
|
|
160
|
-
.rk-login-label-row{display:flex;align-items:baseline;justify-content:space-between;gap:8px}
|
|
161
|
-
.rk-login-forgot{font-size:12px;font-weight:600;color:var(--rk-gold-700)}
|
|
162
|
-
.rk-login-forgot:hover{text-decoration:underline}
|
|
163
225
|
.rk-login-eye{padding:0 12px;color:var(--rk-n-500)}
|
|
164
226
|
.rk-login-submit{margin-top:4px}
|
|
227
|
+
.rk-login-code{font-family:var(--rk-font-mono);font-size:20px;letter-spacing:.42em;text-align:center;padding-right:0}
|
|
228
|
+
.rk-login-code::placeholder{letter-spacing:.42em}
|
|
229
|
+
.rk-login-optional{font-weight:500;color:var(--rk-text-faint)}
|
|
165
230
|
|
|
166
231
|
.rk-login-divider{display:flex;align-items:center;gap:14px;color:var(--rk-text-faint);
|
|
167
232
|
font-size:12px;font-weight:600;text-transform:uppercase;letter-spacing:.08em}
|
|
@@ -176,35 +241,7 @@ export function renderReskinLogin() {
|
|
|
176
241
|
const script = `
|
|
177
242
|
(function(){
|
|
178
243
|
var root=document;
|
|
179
|
-
//
|
|
180
|
-
// form, we just relabel copy so the two states read honestly.
|
|
181
|
-
var thumb=root.querySelector('[data-rk-thumb]');
|
|
182
|
-
var title=root.querySelector('[data-rk-title]');
|
|
183
|
-
var subtitle=root.querySelector('[data-rk-subtitle]');
|
|
184
|
-
var submit=root.querySelector('[data-rk-submit]');
|
|
185
|
-
var foot=root.querySelector('[data-rk-foot]');
|
|
186
|
-
var forgot=root.querySelector('[data-rk-forgot]');
|
|
187
|
-
var arrow='<span class="rk-arrow">\\u2192</span>';
|
|
188
|
-
var copy={
|
|
189
|
-
login:{title:'Welcome back',sub:'Log in to pick up where you left off.',btn:'Log in '+arrow,foot:'New to vidfarm? <a href="#" data-rk-foot-link>Start a free trial</a>',forgot:true},
|
|
190
|
-
signup:{title:'Create your studio',sub:'Start making short-form ads in minutes.',btn:'Create account '+arrow,foot:'Already have an account? <a href="#" data-rk-foot-link>Log in</a>',forgot:false}
|
|
191
|
-
};
|
|
192
|
-
root.querySelectorAll('[data-rk-seg]').forEach(function(btn){
|
|
193
|
-
btn.addEventListener('click',function(){
|
|
194
|
-
var mode=btn.getAttribute('data-rk-seg');
|
|
195
|
-
root.querySelectorAll('[data-rk-seg]').forEach(function(b){
|
|
196
|
-
var on=b===btn; b.classList.toggle('is-active',on); b.setAttribute('aria-selected',on?'true':'false');
|
|
197
|
-
});
|
|
198
|
-
if(thumb)thumb.classList.toggle('is-right',mode==='signup');
|
|
199
|
-
var c=copy[mode];
|
|
200
|
-
if(title)title.textContent=c.title;
|
|
201
|
-
if(subtitle)subtitle.textContent=c.sub;
|
|
202
|
-
if(submit)submit.innerHTML=c.btn;
|
|
203
|
-
if(foot)foot.innerHTML=c.foot;
|
|
204
|
-
if(forgot)forgot.style.visibility=c.forgot?'visible':'hidden';
|
|
205
|
-
});
|
|
206
|
-
});
|
|
207
|
-
// password reveal eye
|
|
244
|
+
// password reveal eye (only present in password mode)
|
|
208
245
|
root.querySelectorAll('[data-rk-reveal]').forEach(function(btn){
|
|
209
246
|
btn.addEventListener('click',function(){
|
|
210
247
|
var el=root.getElementById(btn.getAttribute('data-rk-reveal'));
|