Merge branch 'sites' into feat/ts-in-docs

pull/8452/head
Puru Vijay 3 years ago
commit 5a36085e76

@ -1,5 +1,10 @@
# Svelte changelog # Svelte changelog
## Unreleased
* Handle `width`/`height` attributes when spreading ([#6752](https://github.com/sveltejs/svelte/issues/6752))
* Add support for resize observer bindings (`<div bind:contentRect|contentBoxSize|borderBoxSize|devicePixelContentBoxSize>`) ([#8022](https://github.com/sveltejs/svelte/pull/8022))
## 3.58.0 ## 3.58.0
- Add `bind:innerText` for `contenteditable` elements ([#3311](https://github.com/sveltejs/svelte/issues/3311)) - Add `bind:innerText` for `contenteditable` elements ([#3311](https://github.com/sveltejs/svelte/issues/3311))

@ -546,6 +546,11 @@ export interface HTMLAttributes<T extends EventTarget> extends AriaAttributes, D
*/ */
'bind:innerText'?: string | undefined | null; 'bind:innerText'?: string | undefined | null;
readonly 'bind:contentRect'?: DOMRectReadOnly | undefined | null;
readonly 'bind:contentBoxSize'?: Array<{ blockSize: number; inlineSize: number }> | undefined | null; // TODO make this ResizeObserverSize once we require TS>=4.4
readonly 'bind:borderBoxSize'?: Array<{ blockSize: number; inlineSize: number }> | undefined | null; // TODO make this ResizeObserverSize once we require TS>=4.4
readonly 'bind:devicePixelContentBoxSize'?: Array<{ blockSize: number; inlineSize: number }> | undefined | null; // TODO make this ResizeObserverSize once we require TS>=4.4
// SvelteKit // SvelteKit
'data-sveltekit-keepfocus'?: true | '' | 'off' | undefined | null; 'data-sveltekit-keepfocus'?: true | '' | 'off' | undefined | null;
'data-sveltekit-noscroll'?: true | '' | 'off' | undefined | null; 'data-sveltekit-noscroll'?: true | '' | 'off' | undefined | null;

14
package-lock.json generated

@ -10,7 +10,7 @@
"license": "MIT", "license": "MIT",
"devDependencies": { "devDependencies": {
"@ampproject/remapping": "^0.3.0", "@ampproject/remapping": "^0.3.0",
"@jridgewell/sourcemap-codec": "^1.4.14", "@jridgewell/sourcemap-codec": "^1.4.15",
"@rollup/plugin-commonjs": "^11.0.0", "@rollup/plugin-commonjs": "^11.0.0",
"@rollup/plugin-json": "^6.0.0", "@rollup/plugin-json": "^6.0.0",
"@rollup/plugin-node-resolve": "^11.2.1", "@rollup/plugin-node-resolve": "^11.2.1",
@ -185,9 +185,9 @@
} }
}, },
"node_modules/@jridgewell/sourcemap-codec": { "node_modules/@jridgewell/sourcemap-codec": {
"version": "1.4.14", "version": "1.4.15",
"resolved": "https://registry.npmjs.org/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.4.14.tgz", "resolved": "https://registry.npmjs.org/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.4.15.tgz",
"integrity": "sha512-XPSJHWmi394fuUuzDnGz1wiKqWfo1yXecHQMRf2l6hztTO+nPru658AyDngaBe7isIxEkRsPR3FZh+s7iVa4Uw==", "integrity": "sha512-eF2rxCRulEKXHTRiDrDy6erMYWqNw4LPdQ8UQA4huuxaQsVeRPFl2oM8oDGxMFhJUWZf9McpLtJasDDZb/Bpeg==",
"dev": true "dev": true
}, },
"node_modules/@nodelib/fs.scandir": { "node_modules/@nodelib/fs.scandir": {
@ -5526,9 +5526,9 @@
"dev": true "dev": true
}, },
"@jridgewell/sourcemap-codec": { "@jridgewell/sourcemap-codec": {
"version": "1.4.14", "version": "1.4.15",
"resolved": "https://registry.npmjs.org/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.4.14.tgz", "resolved": "https://registry.npmjs.org/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.4.15.tgz",
"integrity": "sha512-XPSJHWmi394fuUuzDnGz1wiKqWfo1yXecHQMRf2l6hztTO+nPru658AyDngaBe7isIxEkRsPR3FZh+s7iVa4Uw==", "integrity": "sha512-eF2rxCRulEKXHTRiDrDy6erMYWqNw4LPdQ8UQA4huuxaQsVeRPFl2oM8oDGxMFhJUWZf9McpLtJasDDZb/Bpeg==",
"dev": true "dev": true
}, },
"@nodelib/fs.scandir": { "@nodelib/fs.scandir": {

@ -120,7 +120,7 @@
"homepage": "https://svelte.dev", "homepage": "https://svelte.dev",
"devDependencies": { "devDependencies": {
"@ampproject/remapping": "^0.3.0", "@ampproject/remapping": "^0.3.0",
"@jridgewell/sourcemap-codec": "^1.4.14", "@jridgewell/sourcemap-codec": "^1.4.15",
"@rollup/plugin-commonjs": "^11.0.0", "@rollup/plugin-commonjs": "^11.0.0",
"@rollup/plugin-json": "^6.0.0", "@rollup/plugin-json": "^6.0.0",
"@rollup/plugin-node-resolve": "^11.2.1", "@rollup/plugin-node-resolve": "^11.2.1",

@ -266,7 +266,7 @@ You cannot `export default`, since the default export is the component itself.
<script context="module"> <script context="module">
let totalComponents = 0; let totalComponents = 0;
// this allows an importer to do e.g. // the export keyword allows this function to imported with e.g.
// `import Example, { alertTotal } from './Example.svelte'` // `import Example, { alertTotal } from './Example.svelte'`
export function alertTotal() { export function alertTotal() {
alert(totalComponents); alert(totalComponents);

File diff suppressed because it is too large Load Diff

@ -18,7 +18,7 @@
}, },
"dependencies": { "dependencies": {
"@supabase/supabase-js": "^2.20.0", "@supabase/supabase-js": "^2.20.0",
"@sveltejs/repl": "^0.2.0", "@sveltejs/repl": "^0.4.0",
"cookie": "^0.5.0", "cookie": "^0.5.0",
"devalue": "^4.3.0", "devalue": "^4.3.0",
"do-not-zip": "^1.0.0", "do-not-zip": "^1.0.0",
@ -28,9 +28,9 @@
}, },
"devDependencies": { "devDependencies": {
"@resvg/resvg-js": "^2.4.1", "@resvg/resvg-js": "^2.4.1",
"@sveltejs/adapter-vercel": "^2.4.1", "@sveltejs/adapter-vercel": "^2.4.2",
"@sveltejs/kit": "^1.15.4", "@sveltejs/kit": "^1.15.7",
"@sveltejs/site-kit": "^4.1.1", "@sveltejs/site-kit": "^5.0.3",
"@types/marked": "^4.0.8", "@types/marked": "^4.0.8",
"@types/node": "^18.15.11", "@types/node": "^18.15.11",
"@types/prismjs": "^1.26.0", "@types/prismjs": "^1.26.0",
@ -46,7 +46,7 @@
"rollup": "^3.20.2", "rollup": "^3.20.2",
"rollup-plugin-dts": "^5.3.0", "rollup-plugin-dts": "^5.3.0",
"sass": "^1.62.0", "sass": "^1.62.0",
"satori": "^0.4.7", "satori": "^0.4.11",
"satori-html": "^0.3.2", "satori-html": "^0.3.2",
"shelljs": "^0.8.5", "shelljs": "^0.8.5",
"shiki": "^0.14.1", "shiki": "^0.14.1",
@ -56,6 +56,6 @@
"ts-morph": "^18.0.0", "ts-morph": "^18.0.0",
"typescript": "^5.0.4", "typescript": "^5.0.4",
"vite": "^4.2.1", "vite": "^4.2.1",
"vite-imagetools": "^4.0.18" "vite-imagetools": "^4.0.19"
} }
} }

@ -42,7 +42,7 @@
left: 0; left: 0;
top: 0; top: 0;
height: 100%; height: 100%;
background-color: var(--prime); background-color: var(--sk-theme-1);
transition: width 0.4s; transition: width 0.4s;
} }

@ -42,7 +42,7 @@
return { return {
name: file.slice(0, dot), name: file.slice(0, dot),
type: file.slice(dot + 1), type: file.slice(dot + 1),
source, source
}; };
}) })
.filter((x) => x.type === 'svelte' || x.type === 'js') .filter((x) => x.type === 'svelte' || x.type === 'js')
@ -63,7 +63,7 @@
); );
repl.set({ repl.set({
components, components
}); });
} }
} }
@ -80,10 +80,8 @@
browser && version === 'local' browser && version === 'local'
? `${location.origin}/repl/local` ? `${location.origin}/repl/local`
: `https://unpkg.com/svelte@${version}`; : `https://unpkg.com/svelte@${version}`;
const rollupUrl = `https://unpkg.com/rollup@1/dist/rollup.browser.js`;
</script> </script>
{#if browser} {#if browser}
<Repl bind:this={repl} {svelteUrl} {rollupUrl} embedded relaxed /> <Repl bind:this={repl} {svelteUrl} embedded relaxed />
{/if} {/if}

@ -26,11 +26,11 @@
const res = await fetch(`/apps/destroy`, { const res = await fetch(`/apps/destroy`, {
method: 'POST', method: 'POST',
headers: { headers: {
'content-type': 'application/json', 'content-type': 'application/json'
}, },
body: JSON.stringify({ body: JSON.stringify({
ids: selected, ids: selected
}), })
}); });
if (res.ok) { if (res.ok) {
@ -142,8 +142,8 @@
<style> <style>
.apps { .apps {
padding: var(--top-offset) var(--side-nav) 6rem var(--side-nav); padding: var(--sk-page-padding-top) var(--sk-page-padding-side) 6rem var(--sk-page-padding-side);
max-width: var(--main-width); max-width: var(--sk-page-main-width);
margin: 0 auto; margin: 0 auto;
} }
@ -161,7 +161,7 @@
padding: 0 0 0 3.2rem; padding: 0 0 0 3.2rem;
position: relative; position: relative;
margin: 1rem 0; margin: 1rem 0;
color: var(--text); color: var(--sk-text-2);
} }
.avatar { .avatar {
@ -217,7 +217,7 @@
line-height: 1; line-height: 1;
display: flex; display: flex;
border: 1px solid #eee; border: 1px solid #eee;
border-radius: var(--border-r); border-radius: var(--sk-border-radius);
z-index: 2; z-index: 2;
} }
@ -226,7 +226,7 @@
gap: 1rem; gap: 1rem;
padding: 0 1rem; padding: 0 1rem;
height: 100%; height: 100%;
border-radius: var(--border-r); border-radius: var(--sk-border-radius);
align-items: center; align-items: center;
} }
@ -247,8 +247,8 @@
} }
h2 { h2 {
color: var(--text); color: var(--sk-text-2);
font-size: var(--h5); font-size: var(--sk-text-s);
font-weight: 400; font-weight: 400;
overflow: hidden; overflow: hidden;
text-overflow: ellipsis; text-overflow: ellipsis;
@ -256,11 +256,11 @@
li a { li a {
display: block; display: block;
background: var(--back-light); background: var(--sk-back-3);
padding: 1rem 3rem 1rem 1rem; padding: 1rem 3rem 1rem 1rem;
height: 100%; height: 100%;
line-height: 1; line-height: 1;
border-radius: var(--border-r); border-radius: var(--sk-border-radius);
text-decoration: none; text-decoration: none;
} }
@ -282,7 +282,7 @@
} }
ul:not(.selecting) li:hover a { ul:not(.selecting) li:hover a {
background-color: var(--second); background-color: var(--sk-theme-2);
color: white; color: white;
} }

@ -6,7 +6,6 @@
import { mapbox_setup } from '../../../../config.js'; import { mapbox_setup } from '../../../../config.js';
import AppControls from './AppControls.svelte'; import AppControls from './AppControls.svelte';
/** @type {import('./$types').PageData} */
export let data; export let data;
let version = data.version; let version = data.version;
@ -41,7 +40,7 @@
afterNavigate(() => { afterNavigate(() => {
repl.set({ repl.set({
components: data.gist.components, components: data.gist.components
}); });
}); });
@ -99,11 +98,11 @@
<style> <style>
.repl-outer { .repl-outer {
position: relative; position: relative;
height: calc(100vh - var(--nav-h)); height: calc(100vh - var(--sk-nav-height));
--app-controls-h: 5.6rem; --app-controls-h: 5.6rem;
--pane-controls-h: 4.2rem; --pane-controls-h: 4.2rem;
overflow: hidden; overflow: hidden;
background-color: var(--back); background-color: var(--sk-back-1);
padding: var(--app-controls-h) 0 0 0; padding: var(--app-controls-h) 0 0 0;
/* margin: 0 calc(var(--side-nav) * -1); */ /* margin: 0 calc(var(--side-nav) * -1); */
box-sizing: border-box; box-sizing: border-box;

@ -45,15 +45,15 @@
method: 'POST', method: 'POST',
credentials: 'include', credentials: 'include',
headers: { headers: {
'Content-Type': 'application/json', 'Content-Type': 'application/json'
}, },
body: JSON.stringify({ body: JSON.stringify({
name, name,
files: components.map((component) => ({ files: components.map((component) => ({
name: `${component.name}.${component.type}`, name: `${component.name}.${component.type}`,
source: component.source, source: component.source
})), }))
}), })
}); });
if (r.status < 200 || r.status >= 300) { if (r.status < 200 || r.status >= 300) {
@ -110,15 +110,15 @@
method: 'PUT', method: 'PUT',
credentials: 'include', credentials: 'include',
headers: { headers: {
'Content-Type': 'application/json', 'Content-Type': 'application/json'
}, },
body: JSON.stringify({ body: JSON.stringify({
name, name,
files: components.map((component) => ({ files: components.map((component) => ({
name: `${component.name}.${component.type}`, name: `${component.name}.${component.type}`,
source: component.source, source: component.source
})), }))
}), })
}); });
if (r.status < 200 || r.status >= 300) { if (r.status < 200 || r.status >= 300) {
@ -164,7 +164,7 @@
files.push( files.push(
...components.map((component) => ({ ...components.map((component) => ({
path: `src/${component.name}.${component.type}`, path: `src/${component.name}.${component.type}`,
data: component.source, data: component.source
})) }))
); );
files.push({ files.push({
@ -175,7 +175,7 @@ var app = new App({
target: document.body target: document.body
}); });
export default app;`, export default app;`
}); });
downloadBlob(doNotZip.toBlob(files), 'svelte-app.zip'); downloadBlob(doNotZip.toBlob(files), 'svelte-app.zip');
@ -242,7 +242,7 @@ export default app;`,
display: flex; display: flex;
align-items: center; align-items: center;
justify-content: space-between; justify-content: space-between;
padding: 0.6rem var(--side-nav); padding: 0.6rem var(--sk-page-padding-side);
background-color: var(--sk-back-4); background-color: var(--sk-back-4);
color: var(--sk-text-1); color: var(--sk-text-1);
white-space: nowrap; white-space: nowrap;

@ -47,7 +47,7 @@
/* position: relative; padding: 0 2em 0 0; */ /* position: relative; padding: 0 2em 0 0; */
line-height: 1; line-height: 1;
display: none; display: none;
font-family: var(--font); font-family: var(--sk-font);
font-size: 1.6rem; font-size: 1.6rem;
opacity: 0.7; opacity: 0.7;
} }
@ -72,7 +72,7 @@
min-width: 10em; min-width: 10em;
top: 3rem; top: 3rem;
right: -1.6rem; right: -1.6rem;
background-color: var(--second); background-color: var(--sk-theme-2);
padding: 0.8rem 1.6rem; padding: 0.8rem 1.6rem;
z-index: 99; z-index: 99;
text-align: left; text-align: left;
@ -84,7 +84,7 @@
.menu button, .menu button,
.menu a { .menu a {
background-color: transparent; background-color: transparent;
font-family: var(--font); font-family: var(--sk-font);
font-size: 1.6rem; font-size: 1.6rem;
opacity: 0.7; opacity: 0.7;
padding: 0.4rem 0; padding: 0.4rem 0;

@ -26,7 +26,7 @@
left: 0; left: 0;
width: 100%; width: 100%;
height: 100%; height: 100%;
background-color: var(--back); background-color: var(--sk-back-1);
overflow: hidden; overflow: hidden;
box-sizing: border-box; box-sizing: border-box;
--pane-controls-h: 4.2rem; --pane-controls-h: 4.2rem;

@ -45,7 +45,7 @@
<style> <style>
.container { .container {
padding: var(--top-offset) var(--side-nav) 6rem var(--side-nav); padding: var(--sk-page-padding-top) var(--sk-page-padding-side) 6rem var(--sk-page-padding-side);
} }
h1, h1,
@ -64,10 +64,10 @@
} }
.error { .error {
background-color: var(--second); background-color: var(--sk-theme-2);
color: white; color: white;
padding: 12px 16px; padding: 12px 16px;
font: 600 16px/1.7 var(--font); font: 600 16px/1.7 var(--sk-font);
border-radius: 2px; border-radius: 2px;
} }
</style> </style>

@ -123,12 +123,12 @@ npm run dev
section { section {
position: relative; position: relative;
margin: 10rem auto; margin: 10rem auto;
padding: 0 var(--side-nav); padding: 0 var(--sk-page-padding-side);
max-width: 120rem; max-width: 120rem;
} }
.blurb-shifter { .blurb-shifter {
margin-top: calc(-10rem + var(--side-nav)); margin-top: calc(-10rem + var(--sk-page-padding-side));
} }
footer { footer {
@ -139,7 +139,7 @@ npm run dev
} }
footer a { footer a {
color: var(--text); color: var(--sk-text-2);
padding: 0.5rem 1rem; padding: 0.5rem 1rem;
display: block; display: block;
} }

@ -6,26 +6,26 @@
{ {
id: 'hello-world', id: 'hello-world',
title: 'Hello World', title: 'Hello World',
description: 'Svelte components are built on top of HTML. Just add data.', description: 'Svelte components are built on top of HTML. Just add data.'
}, },
{ {
id: 'nested-components', id: 'nested-components',
title: 'Scoped CSS', title: 'Scoped CSS',
description: description:
'CSS is component-scoped by default — no more style collisions or specificity wars. Or you can <a href="/blog/svelte-css-in-js">use your favourite CSS-in-JS library</a >.', 'CSS is component-scoped by default — no more style collisions or specificity wars. Or you can <a href="/blog/svelte-css-in-js">use your favourite CSS-in-JS library</a >.'
}, },
{ {
id: 'reactive-assignments', id: 'reactive-assignments',
title: 'Reactivity', title: 'Reactivity',
description: description:
'Trigger efficient, granular updates by assigning to local variables. The compiler does the rest.', 'Trigger efficient, granular updates by assigning to local variables. The compiler does the rest.'
}, },
{ {
id: 'svg-transitions', id: 'svg-transitions',
title: 'Transitions', title: 'Transitions',
description: description:
'Build beautiful UIs with a powerful, performant transition engine built right into the framework.', 'Build beautiful UIs with a powerful, performant transition engine built right into the framework.'
}, }
]; ];
let selected = examples[0]; let selected = examples[0];
@ -80,14 +80,14 @@
grid-template-columns: 4fr 1fr; grid-template-columns: 4fr 1fr;
color: white; color: white;
align-items: center; align-items: center;
font-size: var(--h5); font-size: var(--sk-text-s);
} }
.tabs { .tabs {
display: grid; display: grid;
grid-template-columns: repeat(4, 1fr); grid-template-columns: repeat(4, 1fr);
height: 100%; height: 100%;
border-radius: var(--border-r) var(--border-r) 0 0; border-radius: var(--sk-border-radius) var(--sk-border-radius) 0 0;
background-color: rgba(255, 255, 255, 0.1); background-color: rgba(255, 255, 255, 0.1);
} }
@ -98,7 +98,7 @@
height: 100%; height: 100%;
align-items: center; align-items: center;
justify-content: center; justify-content: center;
border-radius: var(--border-r) var(--border-r) 0 0; border-radius: var(--sk-border-radius) var(--sk-border-radius) 0 0;
} }
button:hover { button:hover {
@ -143,7 +143,7 @@
@media (min-width: 960px) { @media (min-width: 960px) {
.controls { .controls {
font-size: var(--h4); font-size: var(--sk-text-s);
} }
.large-show { .large-show {

@ -17,7 +17,7 @@
.repl-container { .repl-container {
width: 100%; width: 100%;
height: 420px; height: 420px;
border-radius: var(--border-r); border-radius: var(--sk-border-radius);
overflow: hidden; overflow: hidden;
} }
</style> </style>

@ -6,7 +6,11 @@
<div class="hero"> <div class="hero">
<strong>Cybernetically enhanced web apps</strong> <strong>Cybernetically enhanced web apps</strong>
<Image src={Machine} alt="The Svelte compiler packaging up your component code" --max-height="65vh" /> <Image
src={Machine}
alt="The Svelte compiler packaging up your component code"
--max-height="65vh"
/>
<img alt="Svelte logotype" class="logotype" src={SvelteLogotype} /> <img alt="Svelte logotype" class="logotype" src={SvelteLogotype} />
</div> </div>
@ -22,13 +26,13 @@
strong { strong {
position: absolute; position: absolute;
font-size: min(4vw, var(--h4)); font-size: min(4vw, var(--sk-text-s));
max-width: 10em; max-width: 10em;
text-transform: uppercase; text-transform: uppercase;
font-weight: 700; font-weight: 700;
color: var(--sk-text-2); color: var(--sk-text-2);
letter-spacing: 0.05em; letter-spacing: 0.05em;
left: max(var(--side-nav), 10%); left: max(var(--sk-page-padding-side), 10%);
top: 25%; top: 25%;
} }
@ -55,15 +59,14 @@
.logotype, .logotype,
strong { strong {
left: calc(var(--side-nav) + 4rem); left: calc(var(--sk-page-padding-side) + 4rem);
/* left: calc(50% - 56rem + var(--side-nav)); */
} }
} }
@media (min-width: 1200px) { @media (min-width: 1200px) {
strong, strong,
.logotype { .logotype {
left: calc(50% - 56rem + var(--side-nav)); left: calc(50% - 56rem + var(--sk-page-padding-side));
} }
} }

@ -10,7 +10,7 @@
.inner { .inner {
max-width: 120rem; max-width: 120rem;
padding: 0 var(--side-nav); padding: 0 var(--sk-page-padding-side);
margin: 0 auto; margin: 0 auto;
} }
</style> </style>

@ -36,7 +36,7 @@
grid-gap: 1em; grid-gap: 1em;
min-height: calc(100vh - var(--sk-nav-height)); min-height: calc(100vh - var(--sk-nav-height));
padding: var(--sk-page-padding-top) var(--sk-page-padding-side) 6rem var(--sk-page-padding-side); padding: var(--sk-page-padding-top) var(--sk-page-padding-side) 6rem var(--sk-page-padding-side);
max-width: var(--main-width); max-width: var(--sk-page-main-width);
margin: 0 auto; margin: 0 auto;
} }
@ -52,7 +52,7 @@
.post:first-child { .post:first-child {
margin: 0 0 2rem 0; margin: 0 0 2rem 0;
padding: 0 0 4rem 0; padding: 0 0 4rem 0;
border-bottom: var(--border-w) solid #6767785b; /* based on --second */ border-bottom: var(--sk-thick-border-width) solid #6767785b; /* based on --second */
} }
.post:first-child h2 { .post:first-child h2 {

@ -36,7 +36,7 @@
<style> <style>
.post { .post {
padding: var(--sk-page-padding-top) var(--sk-page-padding-side) 6rem var(--sk-page-padding-side); padding: var(--sk-page-padding-top) var(--sk-page-padding-side) 6rem var(--sk-page-padding-side);
max-width: var(--main-width); max-width: var(--sk-page-main-width);
margin: 0 auto; margin: 0 auto;
} }
@ -155,7 +155,7 @@
@media (min-width: 910px) { @media (min-width: 910px) {
.post :global(.max) { .post :global(.max) {
width: calc(100vw - 2 * var(--sk-page-padding-side)); width: calc(100vw - 2 * var(--sk-page-padding-side));
margin: 0 calc(var(--main-width) / 2 - 50vw); margin: 0 calc(var(--sk-page-main-width) / 2 - 50vw);
text-align: center; text-align: center;
} }

@ -18,7 +18,7 @@
const clone = (file) => ({ const clone = (file) => ({
name: file.name.replace(/.\w+$/, ''), name: file.name.replace(/.\w+$/, ''),
type: file.type, type: file.type,
source: file.content, source: file.content
}); });
$: mobile = width < 768; // note: same as per media query below $: mobile = width < 768; // note: same as per media query below
@ -112,7 +112,7 @@
height: 100%; height: 100%;
display: grid; display: grid;
/* TODO */ /* TODO */
grid-template-columns: var(--sidebar-mid-w) auto; grid-template-columns: 36rem auto;
grid-auto-rows: 100%; grid-auto-rows: 100%;
transition: none; transition: none;
} }

@ -50,7 +50,7 @@
overflow-y: auto; overflow-y: auto;
height: 100%; height: 100%;
border-right: 1px solid var(--sk-back-4); border-right: 1px solid var(--sk-back-4);
background-color: var(--sk-back-4); background-color: var(--sk-back-3);
color: var(--sk-text-2); color: var(--sk-text-2);
padding: 3rem 3rem 0 3rem; padding: 3rem 3rem 0 3rem;
margin: 0; margin: 0;

@ -34,8 +34,7 @@
grid-gap: 1em; grid-gap: 1em;
min-height: calc(100vh - var(--sk-nav-height)); min-height: calc(100vh - var(--sk-nav-height));
padding: var(--sk-page-padding-top) var(--sk-page-padding-side) 6rem var(--sk-page-padding-side); padding: var(--sk-page-padding-top) var(--sk-page-padding-side) 6rem var(--sk-page-padding-side);
/* TODO: REMOVE */ max-width: var(--sk-page-main-width);
max-width: var(--main-width);
margin: 0 auto; margin: 0 auto;
tab-size: 2; tab-size: 2;
} }

@ -1,10 +1,9 @@
<script> <script>
import Repl from '@sveltejs/repl';
import ScreenToggle from '$lib/components/ScreenToggle.svelte';
import TableOfContents from './TableOfContents.svelte';
import { browser } from '$app/environment'; import { browser } from '$app/environment';
import ScreenToggle from '$lib/components/ScreenToggle.svelte';
import Repl from '@sveltejs/repl';
import { mapbox_setup, svelteUrl } from '../../../config.js'; import { mapbox_setup, svelteUrl } from '../../../config.js';
import TableOfContents from './TableOfContents.svelte';
import '@sveltejs/site-kit/styles/code.css'; import '@sveltejs/site-kit/styles/code.css';
@ -32,7 +31,7 @@
slug: chapter.slug, slug: chapter.slug,
section, section,
chapter, chapter,
prev, prev
}; };
lookup.set(chapter.slug, obj); lookup.set(chapter.slug, obj);
@ -54,13 +53,13 @@
const clone = (file) => ({ const clone = (file) => ({
name: file.name.replace(/.\w+$/, ''), name: file.name.replace(/.\w+$/, ''),
type: file.type, type: file.type,
source: file.content, source: file.content
}); });
$: if (repl) { $: if (repl) {
completed = false; completed = false;
repl.set({ repl.set({
components: data.tutorial.initial.map(clone), components: data.tutorial.initial.map(clone)
}); });
} }
@ -68,13 +67,13 @@
function reset() { function reset() {
repl.update({ repl.update({
components: data.tutorial.initial.map(clone), components: data.tutorial.initial.map(clone)
}); });
} }
function complete() { function complete() {
repl.update({ repl.update({
components: data.tutorial.complete.map(clone), components: data.tutorial.complete.map(clone)
}); });
} }
@ -188,7 +187,7 @@
height: 100%; height: 100%;
display: grid; display: grid;
/* TODO */ /* TODO */
grid-template-columns: minmax(33.333%, var(--sidebar-large-w)) auto; grid-template-columns: minmax(33.333%, 48rem) auto;
grid-auto-rows: 100%; grid-auto-rows: 100%;
transition: none; transition: none;
} }
@ -204,7 +203,7 @@
flex-direction: column; flex-direction: column;
height: 100%; height: 100%;
border-right: 1px solid var(--sk-back-4); border-right: 1px solid var(--sk-back-4);
background-color: var(--sk-back-4); background-color: var(--sk-back-3);
color: var(--sk-text-2); color: var(--sk-text-2);
} }
@ -287,6 +286,7 @@
padding: 1rem 1rem; padding: 1rem 1rem;
box-shadow: inset 1px 1px 6px hsla(205.7, 63.6%, 30.8%, 0.06); box-shadow: inset 1px 1px 6px hsla(205.7, 63.6%, 30.8%, 0.06);
border-radius: 0.5rem; border-radius: 0.5rem;
--shiki-color-background: var(--sk-back-1);
} }
.controls { .controls {

@ -3,7 +3,7 @@ import get_object from '../utils/get_object';
import Expression from './shared/Expression'; import Expression from './shared/Expression';
import Component from '../Component'; import Component from '../Component';
import TemplateScope from './shared/TemplateScope'; import TemplateScope from './shared/TemplateScope';
import { regex_dimensions } from '../../utils/patterns'; import { regex_dimensions, regex_box_size } from '../../utils/patterns';
import { Node as ESTreeNode } from 'estree'; import { Node as ESTreeNode } from 'estree';
import { TemplateNode } from '../../interfaces'; import { TemplateNode } from '../../interfaces';
import Element from './Element'; import Element from './Element';
@ -92,6 +92,7 @@ export default class Binding extends Node {
this.is_readonly = this.is_readonly =
regex_dimensions.test(this.name) || regex_dimensions.test(this.name) ||
regex_box_size.test(this.name) ||
(isElement(parent) && (isElement(parent) &&
((parent.is_media_node() && read_only_media_attributes.has(this.name)) || ((parent.is_media_node() && read_only_media_attributes.has(this.name)) ||
(parent.name === 'input' && type === 'file')) /* TODO others? */); (parent.name === 'input' && type === 'file')) /* TODO others? */);

@ -12,7 +12,7 @@ import Text from './Text';
import { namespaces } from '../../utils/namespaces'; import { namespaces } from '../../utils/namespaces';
import map_children from './shared/map_children'; import map_children from './shared/map_children';
import { is_name_contenteditable, get_contenteditable_attr } from '../utils/contenteditable'; import { is_name_contenteditable, get_contenteditable_attr } from '../utils/contenteditable';
import { regex_dimensions, regex_starts_with_newline, regex_non_whitespace_character } from '../../utils/patterns'; import { regex_dimensions, regex_starts_with_newline, regex_non_whitespace_character, regex_box_size } from '../../utils/patterns';
import fuzzymatch from '../../utils/fuzzymatch'; import fuzzymatch from '../../utils/fuzzymatch';
import list from '../../utils/list'; import list from '../../utils/list';
import Let from './Let'; import Let from './Let';
@ -1090,7 +1090,10 @@ export default class Element extends Node {
} else if (contenteditable && !contenteditable.is_static) { } else if (contenteditable && !contenteditable.is_static) {
return component.error(contenteditable, compiler_errors.dynamic_contenteditable_attribute); return component.error(contenteditable, compiler_errors.dynamic_contenteditable_attribute);
} }
} else if (name !== 'this') { } else if (
name !== 'this' &&
!regex_box_size.test(name)
) {
return component.error(binding, compiler_errors.invalid_binding(binding.name)); return component.error(binding, compiler_errors.invalid_binding(binding.name));
} }
}); });

@ -11,6 +11,7 @@ import { Node, Identifier } from 'estree';
import add_to_set from '../../../utils/add_to_set'; import add_to_set from '../../../utils/add_to_set';
import mark_each_block_bindings from '../shared/mark_each_block_bindings'; import mark_each_block_bindings from '../shared/mark_each_block_bindings';
import handle_select_value_binding from './handle_select_value_binding'; import handle_select_value_binding from './handle_select_value_binding';
import { regex_box_size } from '../../../../utils/patterns';
export default class BindingWrapper { export default class BindingWrapper {
node: Binding; node: Binding;
@ -455,7 +456,12 @@ function get_value_from_dom(
return x`$$value`; return x`$$value`;
} }
// <select bind:value='selected'> // <div bind:contentRect|contentBoxSize|borderBoxSize|devicePixelContentBoxSize>
if (regex_box_size.test(name)) {
return x`@ResizeObserverSingleton.entries.get(this)?.${name}`;
}
// <select bind:value='selected>
if (node.name === 'select') { if (node.name === 'select') {
return node.get_static_attribute_value('multiple') === true ? return node.get_static_attribute_value('multiple') === true ?
x`@select_multiple_value(this)` : x`@select_multiple_value(this)` :

@ -12,7 +12,7 @@ import { namespaces } from '../../../../utils/namespaces';
import AttributeWrapper from './Attribute'; import AttributeWrapper from './Attribute';
import StyleAttributeWrapper from './StyleAttribute'; import StyleAttributeWrapper from './StyleAttribute';
import SpreadAttributeWrapper from './SpreadAttribute'; import SpreadAttributeWrapper from './SpreadAttribute';
import { regex_dimensions, regex_starts_with_newline, regex_backslashes } from '../../../../utils/patterns'; import { regex_dimensions, regex_starts_with_newline, regex_backslashes, regex_border_box_size, regex_content_box_size, regex_device_pixel_content_box_size, regex_content_rect } from '../../../../utils/patterns';
import Binding from './Binding'; import Binding from './Binding';
import add_to_set from '../../../utils/add_to_set'; import add_to_set from '../../../utils/add_to_set';
import { add_event_handler } from '../shared/add_event_handlers'; import { add_event_handler } from '../shared/add_event_handlers';
@ -64,11 +64,29 @@ const events = [
filter: (node: Element, _name: string) => filter: (node: Element, _name: string) =>
node.name === 'input' && node.get_static_attribute_value('type') === 'range' node.name === 'input' && node.get_static_attribute_value('type') === 'range'
}, },
// resize events
{ {
event_names: ['elementresize'], event_names: ['elementresize'],
filter: (_node: Element, name: string) => filter: (_node: Element, name: string) =>
regex_dimensions.test(name) regex_dimensions.test(name)
}, },
{
event_names: ['elementresizecontentbox'],
filter: (_node: Element, name: string) =>
regex_content_rect.test(name) ?? regex_content_box_size.test(name)
},
{
event_names: ['elementresizeborderbox'],
filter: (_node: Element, name: string) =>
regex_border_box_size.test(name)
},
{
event_names: ['elementresizedevicepixelcontentbox'],
filter: (_node: Element, name: string) =>
regex_device_pixel_content_box_size.test(name)
},
// media events // media events
{ {
event_names: ['timeupdate'], event_names: ['timeupdate'],
@ -747,14 +765,33 @@ export default class ElementWrapper extends Wrapper {
`); `);
binding_group.events.forEach(name => { binding_group.events.forEach(name => {
if (name === 'elementresize') { if (['elementresize', 'elementresizecontentbox', 'elementresizeborderbox', 'elementresizedevicepixelcontentbox'].indexOf(name) !== -1) {
// special case
const resize_listener = block.get_unique_name(`${this.var.name}_resize_listener`); const resize_listener = block.get_unique_name(`${this.var.name}_resize_listener`);
block.add_variable(resize_listener); block.add_variable(resize_listener);
// Can't dynamically do `@fn[name]`, code-red doesn't know how to resolve it
switch (name) {
case 'elementresize':
block.chunks.mount.push( block.chunks.mount.push(
b`${resize_listener} = @add_resize_listener(${this.var}, ${callee}.bind(${this.var}));` b`${resize_listener} = @add_iframe_resize_listener(${this.var}, ${callee}.bind(${this.var}));`
); );
break;
case 'elementresizecontentbox':
block.chunks.mount.push(
b`${resize_listener} = @resize_observer_content_box.observe(${this.var}, ${callee}.bind(${this.var}));`
);
break;
case 'elementresizeborderbox':
block.chunks.mount.push(
b`${resize_listener} = @resize_observer_border_box.observe(${this.var}, ${callee}.bind(${this.var}));`
);
break;
case 'elementresizedevicepixelcontentbox':
block.chunks.mount.push(
b`${resize_listener} = @resize_observer_device_pixel_content_box.observe(${this.var}, ${callee}.bind(${this.var}));`
);
break;
}
block.chunks.destroy.push( block.chunks.destroy.push(
b`${resize_listener}();` b`${resize_listener}();`

@ -22,3 +22,9 @@ export const regex_ends_with_underscore = /_$/;
export const regex_invalid_variable_identifier_characters = /[^a-zA-Z0-9_$]/g; export const regex_invalid_variable_identifier_characters = /[^a-zA-Z0-9_$]/g;
export const regex_dimensions = /^(?:offset|client)(?:Width|Height)$/; export const regex_dimensions = /^(?:offset|client)(?:Width|Height)$/;
export const regex_content_rect = /^(?:contentRect)$/;
export const regex_content_box_size = /^(?:contentBoxSize)$/;
export const regex_border_box_size = /^(?:borderBoxSize)$/;
export const regex_device_pixel_content_box_size = /^(?:devicePixelContentBoxSize)$/;
export const regex_box_size = /^(?:contentRect|contentBoxSize|borderBoxSize|devicePixelContentBoxSize)$/;

@ -0,0 +1,69 @@
import { globals } from './globals';
/**
* Resize observer singleton.
* One listener per element only!
* https://groups.google.com/a/chromium.org/g/blink-dev/c/z6ienONUb5A/m/F5-VcUZtBAAJ
*/
export class ResizeObserverSingleton {
constructor(readonly options?: ResizeObserverOptions) {}
observe(element: Element, listener: Listener) {
this._listeners.set(element, listener);
this._getObserver().observe(element, this.options);
return () => {
this._listeners.delete(element);
this._observer.unobserve(element); // this line can probably be removed
};
}
private readonly _listeners: WeakMap<Element, Listener> = 'WeakMap' in globals ? new WeakMap() : undefined;
private _observer?: ResizeObserver;
private _getObserver() {
return this._observer ?? (this._observer = new ResizeObserver((entries) => {
for (const entry of entries) {
(ResizeObserverSingleton as any).entries.set(entry.target, entry);
this._listeners.get(entry.target)?.(entry);
}
}));
}
}
// Needs to be written like this to pass the tree-shake-test
(ResizeObserverSingleton as any).entries = 'WeakMap' in globals ? new WeakMap() : undefined;
type Listener = (entry: ResizeObserverEntry)=>any;
// TODO: Remove this
interface ResizeObserverSize {
readonly blockSize: number;
readonly inlineSize: number;
}
interface ResizeObserverEntry {
readonly borderBoxSize: readonly ResizeObserverSize[];
readonly contentBoxSize: readonly ResizeObserverSize[];
readonly contentRect: DOMRectReadOnly;
readonly devicePixelContentBoxSize: readonly ResizeObserverSize[];
readonly target: Element;
}
type ResizeObserverBoxOptions = 'border-box' | 'content-box' | 'device-pixel-content-box';
interface ResizeObserverOptions {
box?: ResizeObserverBoxOptions;
}
interface ResizeObserver {
disconnect(): void;
observe(target: Element, options?: ResizeObserverOptions): void;
unobserve(target: Element): void;
}
interface ResizeObserverCallback {
(entries: ResizeObserverEntry[], observer: ResizeObserver): void;
}
declare let ResizeObserver: {
prototype: ResizeObserver;
new(callback: ResizeObserverCallback): ResizeObserver;
};

@ -1,3 +1,4 @@
import { ResizeObserverSingleton } from './ResizeObserverSingleton';
import { contenteditable_truthy_values, has_prop } from './utils'; import { contenteditable_truthy_values, has_prop } from './utils';
// Track which nodes are claimed during hydration. Unclaimed nodes can then be removed from the DOM // Track which nodes are claimed during hydration. Unclaimed nodes can then be removed from the DOM
@ -306,6 +307,15 @@ export function attr(node: Element, attribute: string, value?: string) {
else if (node.getAttribute(attribute) !== value) node.setAttribute(attribute, value); else if (node.getAttribute(attribute) !== value) node.setAttribute(attribute, value);
} }
/**
* List of attributes that should always be set through the attr method,
* because updating them through the property setter doesn't work reliably.
* In the example of `width`/`height`, the problem is that the setter only
* accepts numeric values, but the attribute can also be set to a string like `50%`.
* If this list becomes too big, rethink this approach.
*/
const always_set_through_set_attribute = ['width', 'height'];
export function set_attributes(node: Element & ElementCSSInlineStyle, attributes: { [x: string]: string }) { export function set_attributes(node: Element & ElementCSSInlineStyle, attributes: { [x: string]: string }) {
// @ts-ignore // @ts-ignore
const descriptors = Object.getOwnPropertyDescriptors(node.__proto__); const descriptors = Object.getOwnPropertyDescriptors(node.__proto__);
@ -316,7 +326,7 @@ export function set_attributes(node: Element & ElementCSSInlineStyle, attributes
node.style.cssText = attributes[key]; node.style.cssText = attributes[key];
} else if (key === '__value') { } else if (key === '__value') {
(node as any).value = node[key] = attributes[key]; (node as any).value = node[key] = attributes[key];
} else if (descriptors[key] && descriptors[key].set) { } else if (descriptors[key] && descriptors[key].set && always_set_through_set_attribute.indexOf(key) === -1) {
node[key] = attributes[key]; node[key] = attributes[key];
} else { } else {
attr(node, key, attributes[key]); attr(node, key, attributes[key]);
@ -689,7 +699,7 @@ export function is_crossorigin() {
return crossorigin; return crossorigin;
} }
export function add_resize_listener(node: HTMLElement, fn: () => void) { export function add_iframe_resize_listener(node: HTMLElement, fn: () => void) {
const computed_style = getComputedStyle(node); const computed_style = getComputedStyle(node);
if (computed_style.position === 'static') { if (computed_style.position === 'static') {
@ -737,6 +747,11 @@ export function add_resize_listener(node: HTMLElement, fn: () => void) {
}; };
} }
export const resize_observer_content_box = /* @__PURE__ */ new ResizeObserverSingleton({ box: 'content-box' });
export const resize_observer_border_box = /* @__PURE__ */ new ResizeObserverSingleton({ box: 'border-box' });
export const resize_observer_device_pixel_content_box = /* @__PURE__ */ new ResizeObserverSingleton({ box: 'device-pixel-content-box' });
export { ResizeObserverSingleton };
export function toggle_class(element, name, toggle) { export function toggle_class(element, name, toggle) {
element.classList[toggle ? 'add' : 'remove'](name); element.classList[toggle ? 'add' : 'remove'](name);
} }

@ -1,8 +1,8 @@
/* generated by Svelte vX.Y.Z */ /* generated by Svelte vX.Y.Z */
import { import {
SvelteComponent, SvelteComponent,
add_iframe_resize_listener,
add_render_callback, add_render_callback,
add_resize_listener,
detach, detach,
element, element,
init, init,
@ -23,7 +23,7 @@ function create_fragment(ctx) {
}, },
m(target, anchor) { m(target, anchor) {
insert(target, div, anchor); insert(target, div, anchor);
div_resize_listener = add_resize_listener(div, /*div_elementresize_handler*/ ctx[2].bind(div)); div_resize_listener = add_iframe_resize_listener(div, /*div_elementresize_handler*/ ctx[2].bind(div));
}, },
p: noop, p: noop,
i: noop, i: noop,

@ -1,8 +1,8 @@
/* generated by Svelte vX.Y.Z */ /* generated by Svelte vX.Y.Z */
import { import {
SvelteComponent, SvelteComponent,
add_iframe_resize_listener,
add_render_callback, add_render_callback,
add_resize_listener,
detach, detach,
element, element,
init, init,
@ -42,7 +42,7 @@ function create_fragment(ctx) {
}, },
m(target, anchor) { m(target, anchor) {
insert(target, video, anchor); insert(target, video, anchor);
video_resize_listener = add_resize_listener(video, /*video_elementresize_handler*/ ctx[7].bind(video)); video_resize_listener = add_iframe_resize_listener(video, /*video_elementresize_handler*/ ctx[7].bind(video));
if (!mounted) { if (!mounted) {
dispose = [ dispose = [

@ -0,0 +1,4 @@
export default {
// https://github.com/sveltejs/svelte/issues/6752
html: '<img height="100%" width="100%" alt="" />'
};

@ -0,0 +1 @@
<img height="100%" width="100%" alt="" {...$$restProps} />
Loading…
Cancel
Save