@ternkit/tern 1.4.0 → 1.6.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/index.d.ts +2 -1
- package/dist/index.js +2 -1
- package/dist/runtime/builtin.d.ts +1 -0
- package/dist/runtime/builtin.js +140 -0
- package/dist/runtime/deferred.d.ts +6 -1
- package/dist/runtime/deferred.js +31 -13
- package/dist/runtime/i18n.svelte.d.ts +6 -0
- package/dist/runtime/i18n.svelte.js +10 -0
- package/dist/runtime/passkeys.d.ts +21 -0
- package/dist/runtime/passkeys.js +107 -0
- package/dist/runtime/router.svelte.js +2 -1
- package/dist/runtime/types.d.ts +2 -0
- package/dist/runtime/validate.d.ts +2 -1
- package/dist/runtime/validate.js +20 -18
- package/dist/server/index.d.ts +3 -1
- package/dist/server/index.js +8 -4
- package/dist/ui/AccountSection.svelte +75 -0
- package/dist/ui/AccountSection.svelte.d.ts +12 -0
- package/dist/ui/AlertDialog.svelte +5 -2
- package/dist/ui/AuthCard.svelte +64 -0
- package/dist/ui/AuthCard.svelte.d.ts +12 -0
- package/dist/ui/BarChart.svelte +2 -1
- package/dist/ui/Breadcrumb.svelte +2 -1
- package/dist/ui/Calendar.svelte +3 -2
- package/dist/ui/Carousel.svelte +4 -3
- package/dist/ui/ChartFrame.svelte +2 -1
- package/dist/ui/Combobox.svelte +6 -3
- package/dist/ui/Command.svelte +5 -1
- package/dist/ui/ConsentScreen.svelte +7 -6
- package/dist/ui/DataTable.svelte +7 -5
- package/dist/ui/DatePicker.svelte +8 -5
- package/dist/ui/Devices.svelte +50 -0
- package/dist/ui/Devices.svelte.d.ts +23 -0
- package/dist/ui/Dialog.svelte +2 -1
- package/dist/ui/DonutChart.svelte +3 -1
- package/dist/ui/Field.svelte +1 -1
- package/dist/ui/ForgotPassword.svelte +43 -0
- package/dist/ui/ForgotPassword.svelte.d.ts +16 -0
- package/dist/ui/Form.svelte +8 -3
- package/dist/ui/NavigationMenu.svelte +3 -1
- package/dist/ui/Pagination.svelte +5 -3
- package/dist/ui/Passkeys.svelte +73 -0
- package/dist/ui/Passkeys.svelte.d.ts +21 -0
- package/dist/ui/PasswordInput.svelte +2 -1
- package/dist/ui/ResetPassword.svelte +54 -0
- package/dist/ui/ResetPassword.svelte.d.ts +23 -0
- package/dist/ui/Resizable.svelte +3 -1
- package/dist/ui/SelectMenu.svelte +5 -2
- package/dist/ui/Sidebar.svelte +5 -3
- package/dist/ui/SignIn.svelte +48 -12
- package/dist/ui/SignIn.svelte.d.ts +4 -0
- package/dist/ui/SignUp.svelte +10 -8
- package/dist/ui/Slider.svelte +2 -1
- package/dist/ui/Spinner.svelte +3 -1
- package/dist/ui/Switch.svelte +2 -1
- package/dist/ui/Table.svelte +3 -1
- package/dist/ui/Toaster.svelte +3 -2
- package/dist/ui/Toggle.svelte +2 -0
- package/dist/ui/ToggleGroup.svelte +2 -0
- package/dist/ui/accountDates.d.ts +1 -0
- package/dist/ui/accountDates.js +15 -0
- package/dist/ui/announce.d.ts +4 -0
- package/dist/ui/announce.js +14 -0
- package/dist/ui/index.d.ts +4 -0
- package/dist/ui/index.js +4 -0
- package/dist/vite/index.js +2 -1
- package/dist/vite/native.d.ts +3 -0
- package/dist/vite/native.js +139 -0
- package/package.json +3 -2
package/dist/ui/Toggle.svelte
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
<script lang="ts">
|
|
2
|
+
import { announce } from './announce.js';
|
|
2
3
|
import type { Snippet } from 'svelte';
|
|
3
4
|
import type { HTMLButtonAttributes } from 'svelte/elements';
|
|
4
5
|
|
|
@@ -18,6 +19,7 @@
|
|
|
18
19
|
</script>
|
|
19
20
|
|
|
20
21
|
<button
|
|
22
|
+
use:announce={pressed}
|
|
21
23
|
type="button"
|
|
22
24
|
class="tern-toggle {variant} {size} {klass}"
|
|
23
25
|
aria-pressed={pressed}
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
<script lang="ts">
|
|
2
|
+
import { announce } from './announce.js';
|
|
2
3
|
import type { Snippet } from 'svelte';
|
|
3
4
|
import { getField } from './field.js';
|
|
4
5
|
|
|
@@ -58,6 +59,7 @@
|
|
|
58
59
|
</script>
|
|
59
60
|
|
|
60
61
|
<div
|
|
62
|
+
use:announce={value}
|
|
61
63
|
class="tern-toggle-group {size} {klass}"
|
|
62
64
|
role={type === 'single' ? 'radiogroup' : 'group'}
|
|
63
65
|
aria-label={field ? undefined : label}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export declare function when(iso: string | null | undefined): string;
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
// Dates on the account screens, in the user's locale.
|
|
2
|
+
import { i18n } from '../runtime/i18n.svelte.js';
|
|
3
|
+
export function when(iso) {
|
|
4
|
+
if (!iso)
|
|
5
|
+
return '';
|
|
6
|
+
const d = new Date(iso);
|
|
7
|
+
if (Number.isNaN(d.getTime()))
|
|
8
|
+
return '';
|
|
9
|
+
try {
|
|
10
|
+
return new Intl.DateTimeFormat(i18n.locale || undefined, { dateStyle: 'medium', timeStyle: 'short' }).format(d);
|
|
11
|
+
}
|
|
12
|
+
catch {
|
|
13
|
+
return d.toISOString().slice(0, 16).replace('T', ' ');
|
|
14
|
+
}
|
|
15
|
+
}
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
// Controls that post through hidden inputs (Combobox, SelectMenu,
|
|
2
|
+
// DatePicker, Slider, …) don't fire input events as the user changes
|
|
3
|
+
// them. announce does: on the element it's on, after each change of its
|
|
4
|
+
// parameter, so a Form checks the field as the user changes it.
|
|
5
|
+
/** A Svelte action: use:announce={value} fires input when value changes. */
|
|
6
|
+
export function announce(node, _value) {
|
|
7
|
+
return {
|
|
8
|
+
update() {
|
|
9
|
+
// After Svelte has written the new value to the DOM, which it does
|
|
10
|
+
// after calling update, so the form reads what the user chose.
|
|
11
|
+
queueMicrotask(() => node.dispatchEvent(new Event('input', { bubbles: true })));
|
|
12
|
+
}
|
|
13
|
+
};
|
|
14
|
+
}
|
package/dist/ui/index.d.ts
CHANGED
|
@@ -51,6 +51,10 @@ export { default as Sheet } from './Sheet.svelte';
|
|
|
51
51
|
export { default as Sidebar } from './Sidebar.svelte';
|
|
52
52
|
export { default as SignIn } from './SignIn.svelte';
|
|
53
53
|
export { default as SignUp } from './SignUp.svelte';
|
|
54
|
+
export { default as ForgotPassword } from './ForgotPassword.svelte';
|
|
55
|
+
export { default as ResetPassword } from './ResetPassword.svelte';
|
|
56
|
+
export { default as Devices } from './Devices.svelte';
|
|
57
|
+
export { default as Passkeys } from './Passkeys.svelte';
|
|
54
58
|
export { default as Skeleton } from './Skeleton.svelte';
|
|
55
59
|
export { default as Slider } from './Slider.svelte';
|
|
56
60
|
export { default as Sparkline } from './Sparkline.svelte';
|
package/dist/ui/index.js
CHANGED
|
@@ -54,6 +54,10 @@ export { default as Sheet } from './Sheet.svelte';
|
|
|
54
54
|
export { default as Sidebar } from './Sidebar.svelte';
|
|
55
55
|
export { default as SignIn } from './SignIn.svelte';
|
|
56
56
|
export { default as SignUp } from './SignUp.svelte';
|
|
57
|
+
export { default as ForgotPassword } from './ForgotPassword.svelte';
|
|
58
|
+
export { default as ResetPassword } from './ResetPassword.svelte';
|
|
59
|
+
export { default as Devices } from './Devices.svelte';
|
|
60
|
+
export { default as Passkeys } from './Passkeys.svelte';
|
|
57
61
|
export { default as Skeleton } from './Skeleton.svelte';
|
|
58
62
|
export { default as Slider } from './Slider.svelte';
|
|
59
63
|
export { default as Sparkline } from './Sparkline.svelte';
|
package/dist/vite/index.js
CHANGED
|
@@ -2,6 +2,7 @@ import { svelte } from '@sveltejs/vite-plugin-svelte';
|
|
|
2
2
|
import fs from 'node:fs';
|
|
3
3
|
import { createRequire } from 'node:module';
|
|
4
4
|
import path from 'node:path';
|
|
5
|
+
import { nativePlugin } from './native.js';
|
|
5
6
|
import { goScriptPlugin, goScriptPreprocessor } from './goscript.js';
|
|
6
7
|
import { imagePlugin } from './image.js';
|
|
7
8
|
/** Packages whose browser build works in the server renderer and whose default build needs Node. */
|
|
@@ -218,7 +219,7 @@ export function tern(options = {}) {
|
|
|
218
219
|
return user;
|
|
219
220
|
}
|
|
220
221
|
};
|
|
221
|
-
return [browserBuildsPlugin, imagePlugin(), goScriptPlugin(() => root), ...svelte(svelteOptions), plugin];
|
|
222
|
+
return [browserBuildsPlugin, imagePlugin(), goScriptPlugin(() => root), ...svelte(svelteOptions), plugin, nativePlugin(() => root, SERVER_ENTRY)];
|
|
222
223
|
}
|
|
223
224
|
/** The $service-worker module: what this build produced, for caching. */
|
|
224
225
|
function serviceWorkerModule(root, base) {
|
|
@@ -0,0 +1,139 @@
|
|
|
1
|
+
import { parse } from 'acorn';
|
|
2
|
+
import fs from 'node:fs';
|
|
3
|
+
import path from 'node:path';
|
|
4
|
+
export const NATIVE_IR = '.tern/native/ir.json';
|
|
5
|
+
function svelteVersion(root) {
|
|
6
|
+
try {
|
|
7
|
+
const pkg = path.join(path.dirname(require_resolve('svelte/package.json', root)));
|
|
8
|
+
return JSON.parse(fs.readFileSync(path.join(pkg, 'package.json'), 'utf8')).version;
|
|
9
|
+
}
|
|
10
|
+
catch {
|
|
11
|
+
return '';
|
|
12
|
+
}
|
|
13
|
+
}
|
|
14
|
+
function require_resolve(spec, root) {
|
|
15
|
+
// Find svelte's package.json from the app's node_modules, as Vite does.
|
|
16
|
+
let dir = root;
|
|
17
|
+
for (;;) {
|
|
18
|
+
const candidate = path.join(dir, 'node_modules', spec);
|
|
19
|
+
if (fs.existsSync(candidate))
|
|
20
|
+
return candidate;
|
|
21
|
+
const up = path.dirname(dir);
|
|
22
|
+
if (up === dir)
|
|
23
|
+
throw new Error(`cannot find ${spec}`);
|
|
24
|
+
dir = up;
|
|
25
|
+
}
|
|
26
|
+
}
|
|
27
|
+
export function nativePlugin(getRoot, entry) {
|
|
28
|
+
const modules = new Map();
|
|
29
|
+
let active = false;
|
|
30
|
+
let env = {};
|
|
31
|
+
let base = '/';
|
|
32
|
+
// Asset URLs are placeholders in a module (import.meta.ROLLDOWN_FILE_URL_…)
|
|
33
|
+
// until the bundle is written: their final URLs go in the IR.
|
|
34
|
+
const fileRefs = new Set();
|
|
35
|
+
const fileUrls = {};
|
|
36
|
+
const bundled = {};
|
|
37
|
+
const rel = (file) => path.relative(getRoot(), file).split(path.sep).join('/');
|
|
38
|
+
// Every module is recorded, Svelte's own runtime included: compiling its
|
|
39
|
+
// code, rather than rewriting it, keeps the output exactly Svelte's.
|
|
40
|
+
const native = (_file) => false;
|
|
41
|
+
return {
|
|
42
|
+
name: 'tern:native-ir',
|
|
43
|
+
enforce: 'post',
|
|
44
|
+
configResolved(config) {
|
|
45
|
+
active = !!config.build.ssr && process.env.TERN_NATIVE === '1';
|
|
46
|
+
env = JSON.parse(JSON.stringify({ ...config.env, SSR: true }));
|
|
47
|
+
base = config.base || '/';
|
|
48
|
+
},
|
|
49
|
+
async transform(code, id) {
|
|
50
|
+
if (!active || id.startsWith('\0'))
|
|
51
|
+
return null;
|
|
52
|
+
// Modules with a query, such as an asset's ?url, are recorded under
|
|
53
|
+
// their whole id; what isn't JavaScript fails to parse and is left out.
|
|
54
|
+
const file = id;
|
|
55
|
+
const query = id.includes('?');
|
|
56
|
+
if ((!query && !/\.(svelte|[cm]?[jt]s|[jt]sx|json)$/.test(file)) || native(file))
|
|
57
|
+
return null;
|
|
58
|
+
try {
|
|
59
|
+
const ast = parse(code, { ecmaVersion: 'latest', sourceType: 'module' });
|
|
60
|
+
const imports = {};
|
|
61
|
+
const sources = [];
|
|
62
|
+
for (const node of ast.body) {
|
|
63
|
+
if (node.type === 'ImportDeclaration' || node.type === 'ExportAllDeclaration' || (node.type === 'ExportNamedDeclaration' && node.source)) {
|
|
64
|
+
sources.push(node.source.value);
|
|
65
|
+
}
|
|
66
|
+
}
|
|
67
|
+
// import('./x') with a literal resolves like a static import.
|
|
68
|
+
const walk = (n) => {
|
|
69
|
+
if (!n || typeof n !== 'object')
|
|
70
|
+
return;
|
|
71
|
+
if (Array.isArray(n))
|
|
72
|
+
return n.forEach(walk);
|
|
73
|
+
const node = n;
|
|
74
|
+
if (node.type === 'ImportExpression' && node.source?.type === 'Literal' && typeof node.source.value === 'string')
|
|
75
|
+
sources.push(node.source.value);
|
|
76
|
+
for (const v of Object.values(node))
|
|
77
|
+
if (v && typeof v === 'object')
|
|
78
|
+
walk(v);
|
|
79
|
+
};
|
|
80
|
+
walk(ast.body);
|
|
81
|
+
for (const source of sources) {
|
|
82
|
+
if (source in imports)
|
|
83
|
+
continue;
|
|
84
|
+
const resolved = await this.resolve(source, id, { ssr: true });
|
|
85
|
+
const target = resolved && !resolved.external && !resolved.id.startsWith('\0') ? resolved.id : null;
|
|
86
|
+
imports[source] = target && !native(target) ? rel(target) : null;
|
|
87
|
+
}
|
|
88
|
+
modules.set(file, { id: rel(file), imports, ast, code });
|
|
89
|
+
for (const m of code.matchAll(/import\.meta\.((?:ROLLDOWN|ROLLUP|VITE)_FILE_URL_([\w$]+))/g))
|
|
90
|
+
fileRefs.add(m[1]);
|
|
91
|
+
}
|
|
92
|
+
catch {
|
|
93
|
+
// Not JavaScript we can read: the module stays unrecorded, so
|
|
94
|
+
// whatever imports it renders with the JavaScript engine.
|
|
95
|
+
}
|
|
96
|
+
return null;
|
|
97
|
+
},
|
|
98
|
+
generateBundle(_opts, bundle) {
|
|
99
|
+
if (!active)
|
|
100
|
+
return;
|
|
101
|
+
// What the bundler kept code of: modules it tree-shook away aren't
|
|
102
|
+
// compiled.
|
|
103
|
+
for (const out of Object.values(bundle)) {
|
|
104
|
+
if (out.type !== 'chunk')
|
|
105
|
+
continue;
|
|
106
|
+
for (const [id, m] of Object.entries(out.modules))
|
|
107
|
+
if (m.renderedLength > 0)
|
|
108
|
+
bundled[rel(id)] = true;
|
|
109
|
+
}
|
|
110
|
+
for (const ref of fileRefs) {
|
|
111
|
+
try {
|
|
112
|
+
fileUrls[ref] = path.posix.join(base, this.getFileName(ref.replace(/^(?:ROLLDOWN|ROLLUP|VITE)_FILE_URL_/, '')));
|
|
113
|
+
}
|
|
114
|
+
catch {
|
|
115
|
+
// Not a file of this build: the module falls back.
|
|
116
|
+
}
|
|
117
|
+
}
|
|
118
|
+
},
|
|
119
|
+
closeBundle() {
|
|
120
|
+
if (!active)
|
|
121
|
+
return;
|
|
122
|
+
const root = getRoot();
|
|
123
|
+
const out = path.join(root, NATIVE_IR);
|
|
124
|
+
fs.mkdirSync(path.dirname(out), { recursive: true });
|
|
125
|
+
const ir = { version: 1, svelte: svelteVersion(root), entry, env, fileUrls, bundled, modules: [...modules.values()] };
|
|
126
|
+
try {
|
|
127
|
+
// BigInt literals keep their digits in the node's bigint field;
|
|
128
|
+
// their value, which JSON can't hold, is left out.
|
|
129
|
+
fs.writeFileSync(out, JSON.stringify(ir, (_k, v) => (typeof v === 'bigint' ? null : v)));
|
|
130
|
+
}
|
|
131
|
+
catch (err) {
|
|
132
|
+
// Native rendering is an optimisation: without the IR, tern build
|
|
133
|
+
// skips it and pages render with the JavaScript engine.
|
|
134
|
+
fs.rmSync(out, { force: true });
|
|
135
|
+
this.warn(`native rendering skipped: ${err.message}`);
|
|
136
|
+
}
|
|
137
|
+
}
|
|
138
|
+
};
|
|
139
|
+
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@ternkit/tern",
|
|
3
|
-
"version": "1.
|
|
3
|
+
"version": "1.6.0",
|
|
4
4
|
"description": "Client runtime and Vite plugin for Tern: Svelte on the client, Go on the server",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"type": "module",
|
|
@@ -71,7 +71,8 @@
|
|
|
71
71
|
"vite": "^8.0.0"
|
|
72
72
|
},
|
|
73
73
|
"dependencies": {
|
|
74
|
-
"@sveltejs/vite-plugin-svelte": "^7.3.1"
|
|
74
|
+
"@sveltejs/vite-plugin-svelte": "^7.3.1",
|
|
75
|
+
"acorn": "^8.19.0"
|
|
75
76
|
},
|
|
76
77
|
"devDependencies": {
|
|
77
78
|
"@sveltejs/package": "^3.0.2",
|