@marianmeres/stuic 3.126.1 → 3.128.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.
- package/dist/components/ContactUsForm/ContactUsForm.svelte +571 -0
- package/dist/components/ContactUsForm/ContactUsForm.svelte.d.ts +101 -0
- package/dist/components/ContactUsForm/README.md +211 -0
- package/dist/components/ContactUsForm/_internal/contact-form-i18n-defaults.d.ts +1 -0
- package/dist/components/ContactUsForm/_internal/contact-form-i18n-defaults.js +36 -0
- package/dist/components/ContactUsForm/_internal/contact-form-types.d.ts +59 -0
- package/dist/components/ContactUsForm/_internal/contact-form-types.js +1 -0
- package/dist/components/ContactUsForm/_internal/contact-form-utils.d.ts +17 -0
- package/dist/components/ContactUsForm/_internal/contact-form-utils.js +66 -0
- package/dist/components/ContactUsForm/index.css +22 -0
- package/dist/components/ContactUsForm/index.d.ts +4 -0
- package/dist/components/ContactUsForm/index.js +2 -0
- package/dist/components/Input/Honeypot.svelte +94 -0
- package/dist/components/Input/Honeypot.svelte.d.ts +40 -0
- package/dist/components/Input/README.md +69 -0
- package/dist/components/Input/TimeTrap.svelte +117 -0
- package/dist/components/Input/TimeTrap.svelte.d.ts +52 -0
- package/dist/components/Input/index.d.ts +2 -0
- package/dist/components/Input/index.js +2 -0
- package/dist/components/Pill/index.css +8 -0
- package/dist/index.css +1 -0
- package/dist/index.d.ts +1 -0
- package/dist/index.js +1 -0
- package/package.json +1 -1
|
@@ -0,0 +1,117 @@
|
|
|
1
|
+
<script lang="ts" module>
|
|
2
|
+
import type { HTMLInputAttributes } from "svelte/elements";
|
|
3
|
+
|
|
4
|
+
/** Snapshot returned by `TimeTrap.check()`. */
|
|
5
|
+
export interface TimeTrapSnapshot {
|
|
6
|
+
/** Milliseconds elapsed since the timer armed. */
|
|
7
|
+
elapsedMs: number;
|
|
8
|
+
/** `true` when `elapsedMs < minMs`. */
|
|
9
|
+
isTooFast: boolean;
|
|
10
|
+
/** Epoch ms the timer armed at (client clock), or `undefined` before mount. */
|
|
11
|
+
startedAt: number | undefined;
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
export interface Props extends Omit<HTMLInputAttributes, "value" | "name"> {
|
|
15
|
+
/**
|
|
16
|
+
* Minimum time (ms) a genuine user is expected to need before submitting.
|
|
17
|
+
* Faster submissions are flagged via `isTooFast`. Default: 2000.
|
|
18
|
+
*/
|
|
19
|
+
minMs?: number;
|
|
20
|
+
/**
|
|
21
|
+
* Whether the timer is armed. When false, `isTooFast` stays `false` and no
|
|
22
|
+
* timer runs. Default: true.
|
|
23
|
+
*/
|
|
24
|
+
enabled?: boolean;
|
|
25
|
+
/**
|
|
26
|
+
* `true` until `minMs` has elapsed since mount, then `false`. Bindable and
|
|
27
|
+
* reactive — safe to read directly at submit time. Defaults to `true`
|
|
28
|
+
* (fail-safe: a submit before the timer arms counts as "too fast").
|
|
29
|
+
*/
|
|
30
|
+
isTooFast?: boolean;
|
|
31
|
+
/**
|
|
32
|
+
* Milliseconds elapsed since the timer armed. Updated when the threshold
|
|
33
|
+
* flips and whenever `check()` runs. For an exact submit-time value call
|
|
34
|
+
* `check()`. Bindable. Default: 0.
|
|
35
|
+
*/
|
|
36
|
+
elapsedMs?: number;
|
|
37
|
+
/**
|
|
38
|
+
* Epoch ms captured when the timer armed (client clock). Bindable. Also
|
|
39
|
+
* written into the rendered hidden input so it can ride along in a native
|
|
40
|
+
* form POST. NOTE: this is a client-side heuristic and is not tamper-proof;
|
|
41
|
+
* enforce real rate limiting server-side.
|
|
42
|
+
*/
|
|
43
|
+
startedAt?: number;
|
|
44
|
+
/** Name of the rendered hidden timestamp input. Default: "_ts". */
|
|
45
|
+
name?: string;
|
|
46
|
+
id?: string;
|
|
47
|
+
/** Underlying hidden `<input>` ref. Bindable. */
|
|
48
|
+
input?: HTMLInputElement;
|
|
49
|
+
}
|
|
50
|
+
</script>
|
|
51
|
+
|
|
52
|
+
<script lang="ts">
|
|
53
|
+
import { getId } from "../../utils/get-id.js";
|
|
54
|
+
|
|
55
|
+
let {
|
|
56
|
+
minMs = 2000,
|
|
57
|
+
enabled = true,
|
|
58
|
+
isTooFast = $bindable(true),
|
|
59
|
+
elapsedMs = $bindable(0),
|
|
60
|
+
startedAt = $bindable(),
|
|
61
|
+
name = "_ts",
|
|
62
|
+
id = getId(),
|
|
63
|
+
input = $bindable(),
|
|
64
|
+
...rest
|
|
65
|
+
}: Props = $props();
|
|
66
|
+
|
|
67
|
+
/**
|
|
68
|
+
* Recompute `elapsedMs`/`isTooFast` from the current clock, write them back to
|
|
69
|
+
* the bindings, and return a fresh snapshot. Call at submit time for an exact
|
|
70
|
+
* reading (the reactive `isTooFast` binding is already accurate to timer
|
|
71
|
+
* resolution, but this also refreshes `elapsedMs`).
|
|
72
|
+
*/
|
|
73
|
+
export function check(): TimeTrapSnapshot {
|
|
74
|
+
if (startedAt != null) {
|
|
75
|
+
elapsedMs = Date.now() - startedAt;
|
|
76
|
+
isTooFast = enabled ? elapsedMs < minMs : false;
|
|
77
|
+
} else {
|
|
78
|
+
isTooFast = enabled;
|
|
79
|
+
}
|
|
80
|
+
return { elapsedMs, isTooFast, startedAt };
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
// Re-arm nonce. Writing `startedAt`/`isTooFast`/`elapsedMs` inside the arming
|
|
84
|
+
// $effect does NOT make the effect depend on them (only reads create deps), so
|
|
85
|
+
// reset() can't re-arm by mutating those. Instead it bumps this tracked nonce,
|
|
86
|
+
// which the $effect reads — re-running it clears the old timeout (via cleanup)
|
|
87
|
+
// and schedules a fresh one from the new arm time.
|
|
88
|
+
let armToken = $state(0);
|
|
89
|
+
|
|
90
|
+
/** Re-arm the timer (e.g. after a "send another" reset). */
|
|
91
|
+
export function reset(): void {
|
|
92
|
+
armToken++;
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
// Arm on mount (client only — avoids SSR `Date.now()` in render and any
|
|
96
|
+
// hydration mismatch). A single timeout flips `isTooFast` once the threshold
|
|
97
|
+
// passes; no polling/ticking. Re-runs (re-arms) when `armToken` (reset),
|
|
98
|
+
// `minMs`, or `enabled` change.
|
|
99
|
+
$effect(() => {
|
|
100
|
+
void armToken; // re-arm on reset()
|
|
101
|
+
if (!enabled) {
|
|
102
|
+
isTooFast = false;
|
|
103
|
+
return;
|
|
104
|
+
}
|
|
105
|
+
const armedAt = Date.now();
|
|
106
|
+
startedAt = armedAt;
|
|
107
|
+
isTooFast = true;
|
|
108
|
+
elapsedMs = 0;
|
|
109
|
+
const t = setTimeout(() => {
|
|
110
|
+
isTooFast = false;
|
|
111
|
+
elapsedMs = Date.now() - armedAt;
|
|
112
|
+
}, minMs);
|
|
113
|
+
return () => clearTimeout(t);
|
|
114
|
+
});
|
|
115
|
+
</script>
|
|
116
|
+
|
|
117
|
+
<input bind:this={input} {id} {name} type="hidden" value={startedAt ?? ""} {...rest} />
|
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
import type { HTMLInputAttributes } from "svelte/elements";
|
|
2
|
+
/** Snapshot returned by `TimeTrap.check()`. */
|
|
3
|
+
export interface TimeTrapSnapshot {
|
|
4
|
+
/** Milliseconds elapsed since the timer armed. */
|
|
5
|
+
elapsedMs: number;
|
|
6
|
+
/** `true` when `elapsedMs < minMs`. */
|
|
7
|
+
isTooFast: boolean;
|
|
8
|
+
/** Epoch ms the timer armed at (client clock), or `undefined` before mount. */
|
|
9
|
+
startedAt: number | undefined;
|
|
10
|
+
}
|
|
11
|
+
export interface Props extends Omit<HTMLInputAttributes, "value" | "name"> {
|
|
12
|
+
/**
|
|
13
|
+
* Minimum time (ms) a genuine user is expected to need before submitting.
|
|
14
|
+
* Faster submissions are flagged via `isTooFast`. Default: 2000.
|
|
15
|
+
*/
|
|
16
|
+
minMs?: number;
|
|
17
|
+
/**
|
|
18
|
+
* Whether the timer is armed. When false, `isTooFast` stays `false` and no
|
|
19
|
+
* timer runs. Default: true.
|
|
20
|
+
*/
|
|
21
|
+
enabled?: boolean;
|
|
22
|
+
/**
|
|
23
|
+
* `true` until `minMs` has elapsed since mount, then `false`. Bindable and
|
|
24
|
+
* reactive — safe to read directly at submit time. Defaults to `true`
|
|
25
|
+
* (fail-safe: a submit before the timer arms counts as "too fast").
|
|
26
|
+
*/
|
|
27
|
+
isTooFast?: boolean;
|
|
28
|
+
/**
|
|
29
|
+
* Milliseconds elapsed since the timer armed. Updated when the threshold
|
|
30
|
+
* flips and whenever `check()` runs. For an exact submit-time value call
|
|
31
|
+
* `check()`. Bindable. Default: 0.
|
|
32
|
+
*/
|
|
33
|
+
elapsedMs?: number;
|
|
34
|
+
/**
|
|
35
|
+
* Epoch ms captured when the timer armed (client clock). Bindable. Also
|
|
36
|
+
* written into the rendered hidden input so it can ride along in a native
|
|
37
|
+
* form POST. NOTE: this is a client-side heuristic and is not tamper-proof;
|
|
38
|
+
* enforce real rate limiting server-side.
|
|
39
|
+
*/
|
|
40
|
+
startedAt?: number;
|
|
41
|
+
/** Name of the rendered hidden timestamp input. Default: "_ts". */
|
|
42
|
+
name?: string;
|
|
43
|
+
id?: string;
|
|
44
|
+
/** Underlying hidden `<input>` ref. Bindable. */
|
|
45
|
+
input?: HTMLInputElement;
|
|
46
|
+
}
|
|
47
|
+
declare const TimeTrap: import("svelte").Component<Props, {
|
|
48
|
+
check: () => TimeTrapSnapshot;
|
|
49
|
+
reset: () => void;
|
|
50
|
+
}, "input" | "isTooFast" | "elapsedMs" | "startedAt">;
|
|
51
|
+
type TimeTrap = ReturnType<typeof TimeTrap>;
|
|
52
|
+
export default TimeTrap;
|
|
@@ -1,6 +1,8 @@
|
|
|
1
1
|
export * from "./types.js";
|
|
2
2
|
export { default as FieldAssets, type Props as FieldAssetsProps, type FieldAsset, type FieldAssetUrlObj, type FieldAssetWithBlobUrl, } from "./FieldAssets.svelte";
|
|
3
3
|
export { default as FieldCheckbox, type Props as FieldCheckboxProps, } from "./FieldCheckbox.svelte";
|
|
4
|
+
export { default as Honeypot, type Props as HoneypotProps } from "./Honeypot.svelte";
|
|
5
|
+
export { default as TimeTrap, type Props as TimeTrapProps, type TimeTrapSnapshot, } from "./TimeTrap.svelte";
|
|
4
6
|
export { default as FieldFile, type Props as FieldFileProps } from "./FieldFile.svelte";
|
|
5
7
|
export { default as FieldInput, type Props as FieldInputProps, } from "./FieldInput.svelte";
|
|
6
8
|
export { default as FieldMoney, type Props as FieldMoneyProps, } from "./FieldMoney.svelte";
|
|
@@ -1,6 +1,8 @@
|
|
|
1
1
|
export * from "./types.js";
|
|
2
2
|
export { default as FieldAssets, } from "./FieldAssets.svelte";
|
|
3
3
|
export { default as FieldCheckbox, } from "./FieldCheckbox.svelte";
|
|
4
|
+
export { default as Honeypot } from "./Honeypot.svelte";
|
|
5
|
+
export { default as TimeTrap, } from "./TimeTrap.svelte";
|
|
4
6
|
export { default as FieldFile } from "./FieldFile.svelte";
|
|
5
7
|
export { default as FieldInput, } from "./FieldInput.svelte";
|
|
6
8
|
export { default as FieldMoney, } from "./FieldMoney.svelte";
|
|
@@ -396,6 +396,14 @@
|
|
|
396
396
|
flex-shrink: 0;
|
|
397
397
|
}
|
|
398
398
|
|
|
399
|
+
/* No-intent (neutral) dot: --_color resolves to the muted token, which is also
|
|
400
|
+
the soft variant's background — so the dot would be invisible. Use the muted
|
|
401
|
+
foreground tone instead. Placed before the solid rule so solid keeps --_text
|
|
402
|
+
(equal specificity, later rule wins). */
|
|
403
|
+
.stuic-pill:not([data-intent]) .stuic-pill-dot {
|
|
404
|
+
background: var(--stuic-color-muted-foreground);
|
|
405
|
+
}
|
|
406
|
+
|
|
399
407
|
/* On solid variants the bg already IS the intent color — use foreground instead. */
|
|
400
408
|
.stuic-pill[data-variant="solid"] .stuic-pill-dot {
|
|
401
409
|
background: var(--_text);
|
package/dist/index.css
CHANGED
|
@@ -71,6 +71,7 @@ In practice:
|
|
|
71
71
|
@import "./components/LoginOrRegisterForm/index.css";
|
|
72
72
|
@import "./components/Checkout/index.css";
|
|
73
73
|
@import "./components/CommandMenu/index.css";
|
|
74
|
+
@import "./components/ContactUsForm/index.css";
|
|
74
75
|
@import "./components/CronInput/index.css";
|
|
75
76
|
@import "./components/DataTable/index.css";
|
|
76
77
|
@import "./components/DismissibleMessage/index.css";
|
package/dist/index.d.ts
CHANGED
|
@@ -38,6 +38,7 @@ export * from "./components/Checkout/index.js";
|
|
|
38
38
|
export * from "./components/Collapsible/index.js";
|
|
39
39
|
export * from "./components/ColorScheme/index.js";
|
|
40
40
|
export * from "./components/CommandMenu/index.js";
|
|
41
|
+
export * from "./components/ContactUsForm/index.js";
|
|
41
42
|
export * from "./components/CronInput/index.js";
|
|
42
43
|
export * from "./components/DataTable/index.js";
|
|
43
44
|
export * from "./components/DismissibleMessage/index.js";
|
package/dist/index.js
CHANGED
|
@@ -39,6 +39,7 @@ export * from "./components/Checkout/index.js";
|
|
|
39
39
|
export * from "./components/Collapsible/index.js";
|
|
40
40
|
export * from "./components/ColorScheme/index.js";
|
|
41
41
|
export * from "./components/CommandMenu/index.js";
|
|
42
|
+
export * from "./components/ContactUsForm/index.js";
|
|
42
43
|
export * from "./components/CronInput/index.js";
|
|
43
44
|
export * from "./components/DataTable/index.js";
|
|
44
45
|
export * from "./components/DismissibleMessage/index.js";
|