A music player that connects to your cloud/distributed storage.

feat(facets): builder

+217 -365
-2
_config.ts
··· 36 alias: { 37 "@automerge/automerge": "https://esm.sh/@automerge/automerge@^3.2.3", 38 }, 39 - assetNames: "assets/[name]-[hash]", 40 bundle: true, 41 - chunkNames: "chunks/[name]-[hash]", 42 format: "esm", 43 minify: false, 44 // outExtension: { ".js": ".min.js" },
··· 36 alias: { 37 "@automerge/automerge": "https://esm.sh/@automerge/automerge@^3.2.3", 38 }, 39 bundle: true, 40 format: "esm", 41 minify: false, 42 // outExtension: { ".js": ".min.js" },
+20
src/_components/facets/examples.vto
···
··· 1 + <ul> 2 + {{ for index, item of items }} 3 + <li data-uri="{{ item.url |> facetOrThemeURI }}" data-name="{{item.title}}" style="margin-top: var(--space-md)"> 4 + <div style="display: flex; gap: var(--space-xs); justify-content: space-between;"> 5 + <a href="{{ item.url |> facetLoaderURL }}"> 6 + {{item.title}} 7 + </a> 8 + <button class="button--small button--bg-twist-2" rel="edit"> 9 + <span class="with-icon"> 10 + <i class="ph-fill ph-code-block"></i> 11 + Edit 12 + </span> 13 + </button> 14 + </div> 15 + <div class="list-description"> 16 + {{ item.desc |> md(true) }} 17 + </div> 18 + </li> 19 + {{ /for }} 20 + </ul>
-45
src/_components/facets/list.vto
··· 1 - <ul> 2 - {{ for index, item of items }} 3 - <li data-uri="{{ item.url |> facetOrThemeURI }}" data-name="{{item.title}}"> 4 - <div style="position: relative;"> 5 - <a href="{{ item.url |> facetLoaderURL }}"> 6 - {{item.title}} 7 - </a> 8 - <button 9 - class="button--fixed button--transparent" 10 - popovertarget="facet-menu-{{id}}-{{index}}" 11 - style="anchor-name: --facet-anchor-{{id}}-{{index}}; position: absolute; right: 0; top: 50%; transform: translateY(-50%);" 12 - > 13 - <i class="ph-fill ph-dots-three-circle"></i> 14 - </button> 15 - </div> 16 - <div class="list-description"> 17 - {{item.desc |> md(true)}} 18 - </div> 19 - 20 - <!-- Dropdown Menu --> 21 - <div 22 - id="facet-menu-{{id}}-{{index}}" 23 - class="dropdown" 24 - style="position-anchor: --facet-anchor-{{id}}-{{index}}" 25 - popover 26 - > 27 - <a href="{{ item.url |> facetLoaderURL }}"> 28 - <span class="with-icon"> 29 - <i class="ph-fill ph-globe"></i> Open 30 - </span> 31 - </a> 32 - <a rel="save"> 33 - <span class="with-icon"> 34 - <i class="ph-fill ph-download"></i> Save 35 - </span> 36 - </a> 37 - <a rel="fork"> 38 - <span class="with-icon"> 39 - <i class="ph-fill ph-cursor-text"></i> Edit 40 - </span> 41 - </a> 42 - </div> 43 - </li> 44 - {{ /for }} 45 - </ul>
···
+1 -1
src/_includes/layouts/facets-category.vto
··· 6 {{ await comp.facets.grid({ id: slug, items: categoryFacets }) }} 7 </section> 8 9 - <script src="facets/pages/grid-toggle.js" type="module"></script>
··· 6 {{ await comp.facets.grid({ id: slug, items: categoryFacets }) }} 7 </section> 8 9 + <script src="facets/common/grid-toggle.js" type="module"></script>
+53 -3
src/facets/_index.js src/facets/build.js
··· 7 import * as TID from "@atcute/tid"; 8 9 import * as CID from "~/common/cid.js"; 10 import foundation from "~/common/facets/foundation.js"; 11 - import { signal } from "~/common/signal.js"; 12 import { loadURI } from "~/common/loader.js"; 13 14 /** 15 * @import {Facet} from "~/definitions/types.d.ts" ··· 41 </style> 42 43 <script type="module"> 44 - import foundation from "@diffuse/foundation"; 45 - import { effect } from "./common/signal.js"; 46 47 const components = foundation.features.fillQueueAutomatically(); 48 const myHtmlElement = document.querySelector("#now-playing"); ··· 161 /** 162 * @param {Facet} facet 163 */ 164 async function saveFacet(facet) { 165 const col = output.facets.collection(); 166 const colWithoutId = col.filter((c) => c.id !== facet.id); 167 await output.facets.save([...colWithoutId, { ··· 169 updatedAt: new Date().toISOString(), 170 }]); 171 }
··· 7 import * as TID from "@atcute/tid"; 8 9 import * as CID from "~/common/cid.js"; 10 + import * as Output from "~/common/output.js"; 11 import foundation from "~/common/facets/foundation.js"; 12 + import { facetFromURI } from "~/common/facets/utils.js"; 13 import { loadURI } from "~/common/loader.js"; 14 + import { signal } from "~/common/signal.js"; 15 16 /** 17 * @import {Facet} from "~/definitions/types.d.ts" ··· 43 </style> 44 45 <script type="module"> 46 + import foundation from "~/common/facets/foundation.js"; 47 + import { effect } from "~/common/signal.js"; 48 49 const components = foundation.features.fillQueueAutomatically(); 50 const myHtmlElement = document.querySelector("#now-playing"); ··· 163 /** 164 * @param {Facet} facet 165 */ 166 + 167 async function saveFacet(facet) { 168 + await Output.waitUntilLoaded(output.facets); 169 + 170 const col = output.facets.collection(); 171 const colWithoutId = col.filter((c) => c.id !== facet.id); 172 await output.facets.save([...colWithoutId, { ··· 174 updatedAt: new Date().toISOString(), 175 }]); 176 } 177 + 178 + //////////////////////////////////////////// 179 + // SAVE & FORK 180 + //////////////////////////////////////////// 181 + 182 + document.body.addEventListener( 183 + "click", 184 + /** 185 + * @param {MouseEvent} event 186 + */ 187 + async (event) => { 188 + const target = /** @type {HTMLElement} */ (event.target); 189 + const rel = target.getAttribute("rel"); 190 + if (!rel) return; 191 + 192 + const uri = target.closest("li")?.getAttribute("data-uri"); 193 + if (!uri) return; 194 + 195 + const name = target.closest("li")?.getAttribute("data-name"); 196 + if (!name) return; 197 + 198 + switch (rel) { 199 + case "edit": { 200 + const facet = await facetFromURI({ name, uri }, { fetchHTML: true }); 201 + editFacet(facet); 202 + document.querySelector("#build")?.scrollIntoView(); 203 + break; 204 + } 205 + } 206 + }, 207 + ); 208 + 209 + //////////////////////////////////////////// 210 + // 🚀 211 + //////////////////////////////////////////// 212 + 213 + await Output.waitUntilLoaded(output.facets); 214 + 215 + // Load facet from url 216 + const idParam = new URLSearchParams(location.search).get("id"); 217 + 218 + if (idParam) { 219 + const facet = output.facets.collection().find((f) => f.id === idParam); 220 + if (facet) await editFacet(facet); 221 + }
-253
src/facets/_index.vto
··· 1 - --- 2 - layout: layouts/diffuse.vto 3 - base: ../ 4 - 5 - styles: 6 - - styles/base.css 7 - - styles/diffuse/page.css 8 - - vendor/@phosphor-icons/bold/style.css 9 - - vendor/@phosphor-icons/fill/style.css 10 - 11 - scripts: 12 - - facets/index.js 13 - 14 - examples: 15 - - url: "facets/examples/now-playing/index.html" 16 - title: "Now playing" 17 - desc: > 18 - Shows what's currently set to "now playing" in the queue, along with a button to shift the queue to the next track. 19 - - url: "facets/examples/generate-playlist/index.html" 20 - title: "Generate playlist" 21 - desc: > 22 - Make a list of what previously played in the queue. 23 - --- 24 - 25 - <header> 26 - <div> 27 - <div> 28 - <a class="diffuse-logo" href="./" style="display: inline-block;"> 29 - {{ await comp.diffuse.logo() }} 30 - </a> 31 - </div> 32 - <p class="construct dither-mask" style="margin-top: 0; max-width: none;"> 33 - Facets 34 - </p> 35 - <p> 36 - Facets are various interface components each loaded in their own web page. Every used component is configured so that it operates in broadcast mode, making all the pages communicate with each other. 37 - </p> 38 - 39 - <ul class="table-of-contents"> 40 - <li><a href="facets/#collection">Your collection</a></li> 41 - <li><a href="facets/#featured">Featured</a></li> 42 - <li><a href="facets/#usage">Usage</a></li> 43 - <li><a href="facets/#built-in">Built-in</a></li> 44 - <li><a href="facets/#community">Community</a></li> 45 - <li><a href="facets/#build">Build</a></li> 46 - <li><a href="facets/#foundation">Foundation</a></li> 47 - <li><a href="facets/#examples">Examples</a></li> 48 - <li><a href="facets/#notes">Notes</a></li> 49 - </ul> 50 - </div> 51 - <div class="dither-mask filler"></div> 52 - </header> 53 - <main> 54 - <!-- FEATURED + USAGE --> 55 - <div class="columns"> 56 - <section class="flex"> 57 - <h2 id="featured">Featured</h2> 58 - 59 - <ol style="list-style: none; padding-left: 0;"> 60 - <li> 61 - <p> 62 - <i class="ph-fill ph-plus"></i> 63 - <strong><a href="{{ ('themes/webamp/configurators/input/facet/index.html') |> facetLoaderURL }}">Add</a></strong> audio from various places on the web and your device. 64 - </p> 65 - </li> 66 - <li> 67 - <p> 68 - <i class="ph-fill ph-queue"></i> 69 - <strong><a href="{{ ('themes/webamp/browser/facet/index.html') |> facetLoaderURL }}">Browse</a></strong> your collection to put something into the queue. 70 - </p> 71 - </li> 72 - <li> 73 - <p> 74 - <i class="ph-fill ph-queue"></i> 75 - <strong><a href="{{ ('facets/tools/auto-queue/index.html') |> facetLoaderURL }}">Automate</a></strong> adding items to the queue, for infinite playback or listening to a playlist. 76 - </p> 77 - </li> 78 - <li> 79 - <p> 80 - <i class="ph-fill ph-music-note"></i> 81 - <strong><a href="{{ ('themes/blur/artwork-controller/facet/index.html') |> facetLoaderURL }}">Play</a></strong> queued songs. 82 - </p> 83 - </li> 84 - <li> 85 - <p> 86 - <i class="ph-fill ph-person"></i> 87 - <strong><a href="{{ ('themes/webamp/configurators/output/facet/index.html') |> facetLoaderURL }}">Manage</a></strong> your user data, sync with your other devices or other people. 88 - </p> 89 - </li> 90 - </ol> 91 - </section> 92 - 93 - <section class="flex"> 94 - <h2 id="usage">Usage</h2> 95 - <p> 96 - To use these facets, simply open whichever ones provide the functionality that you're looking for at a given moment. You can browse existing ones here and create one below. 97 - </p> 98 - <p> 99 - For example, say you want to play music; two options would be: (1) <a href="{{ ('themes/webamp/browser/facet/index.html') |> facetLoaderURL }}">browse</a> for a specific song and add it to the queue, or (2) <a href="{{ ('facets/tools/auto-queue/index.html') |> facetLoaderURL }}">automatically</a> add a bunch of shuffled songs to the queue. Next, you need a way to play the items you added to the queue. That's where a <a href="{{ ('themes/blur/artwork-controller/facet/index.html') |> facetLoaderURL }}">controller</a> could be used. 100 - </p> 101 - <p> 102 - <em>You might ask, why can't I do all of this in just one window? That's what <a href="themes/">themes</a> are for, if you need something more streamlined. If you however want a customised experience, or prefer certain interfaces for certain things, that's what facets are for.</em> 103 - </p> 104 - <p> 105 - <small><i class="ph-fill ph-info"></i> Every facet has access to your audio collection and your user data, along with any other shared state.</small> 106 - </p> 107 - </section> 108 - </div> 109 - 110 - <!-- BUILT-IN + COMMUNITY --> 111 - <div class="columns"> 112 - <section class="flex"> 113 - <h2 id="built-in">Built-in</h2> 114 - 115 - {{ await comp.facets.list({ id: "builtin", items: facets }) }} 116 - </section> 117 - 118 - <section class="flex"> 119 - <h2 id="community">Community</h2> 120 - <p> 121 - Check out some facets from the community and load them here. 122 - </p> 123 - <p> 124 - <small><i class="ph-fill ph-info"></i> Nothing here yet, too early.</small> 125 - </p> 126 - </section> 127 - </div> 128 - 129 - <!-- / --> 130 - <div class="dither-mask filler" style="height: var(--space-2xl); margin-top: var(--space-2xl);"></div> 131 - 132 - <!-- BUILD --> 133 - <section> 134 - <h2 id="build">Build</h2> 135 - 136 - <form id="build-form" class="columns"> 137 - <div class="flex"> 138 - <p style="margin-top: 0"> 139 - If you know a bit of HTML & Javascript, you can write your own or plug in some code you found elsewhere: 140 - </p> 141 - 142 - <div id="html-input-container" class="code-editor monospace-font"> 143 - </div> 144 - </div> 145 - 146 - <div class="flex"> 147 - <p style="margin-top: 0"> 148 - Your code here builds on the <a href="facets/#foundation">foundation</a> listed below, it'll be injected into a <code>&lt;div id="container"&gt;</code> element in the body. 149 - </p> 150 - <p> 151 - <input id="name-input" type="text" placeholder="Name" name="name" required /> 152 - </p> 153 - <p> 154 - <textarea id="description-input" placeholder="Description" name="description" rows="2"></textarea> 155 - </p> 156 - <p> 157 - <span class="button-row"> 158 - <button name="save">Save</button> 159 - <button name="save+open">Save &amp; Open</button> 160 - </span> 161 - </p> 162 - </div> 163 - </form> 164 - </section> 165 - 166 - <!-- FOUNDATION --> 167 - <div class="columns"> 168 - <section class="flex"> 169 - <h2 id="foundation">Foundation</h2> 170 - 171 - <p> 172 - Diffuse comes with a foundation that preconfigures all elements so you don't have to set them up yourself, along with a combination of elements for certain features. It internally tracks the DOM addition of the custom elements, so no need to worry about setting up an element multiple times. 173 - </p> 174 - <p> 175 - <small><i class="ph-fill ph-info"></i> Refer to the <a href="#elements">elements index</a> to find out what each element does.</small> 176 - </p> 177 - <div class="code-block"> 178 - <code> 179 - {{- echo -}} 180 - import foundation from "common/facets/foundation.js" 181 - {{ /echo }} 182 - {{ echo -}}foundation.engine.audio(){{- /echo }} 183 - {{ echo -}}foundation.engine.queue(){{- /echo }} 184 - {{ echo -}}foundation.engine.repeatShuffle(){{- /echo }} 185 - {{ echo -}}foundation.engine.scope(){{- /echo }} 186 - 187 - {{ echo -}}foundation.orchestrator.autoQueue(){{- /echo }} 188 - {{ echo -}}foundation.orchestrator.favourites(){{- /echo }} 189 - {{ echo -}}foundation.orchestrator.input(){{- /echo }} 190 - {{ echo -}}foundation.orchestrator.output(){{- /echo }} 191 - {{ echo -}}foundation.orchestrator.queueAudio(){{- /echo }} 192 - {{ echo -}}foundation.orchestrator.processTracks(){{- /echo }} 193 - {{ echo -}}foundation.orchestrator.scopedTracks(){{- /echo }} 194 - {{ echo -}}foundation.orchestrator.sources(){{- /echo }} 195 - 196 - {{ echo -}}foundation.processor.artwork(){{- /echo }} 197 - {{ echo -}}foundation.processor.metadata(){{- /echo }} 198 - {{ echo -}}foundation.processor.search(){{- /echo -}} 199 - </code> 200 - </div> 201 - 202 - <p> 203 - <small>Features:</small> 204 - </p> 205 - <ul style="margin-bottom: 0;"> 206 - <li> 207 - <span>Fill the queue automatically <small>(infinite play)</small></span> 208 - <div class="list-description"> 209 - <code>foundation.features.fillQueueAutomatically()</code> 210 - </div> 211 - </li> 212 - <li> 213 - <span>Play audio from the queue</span> 214 - <div class="list-description"> 215 - <code>foundation.features.playAudioFromQueue()</code> 216 - </div> 217 - </li> 218 - <li> 219 - <span>Process inputs <small>(into tracks, etc)</small></span> 220 - <div class="list-description"> 221 - <code>foundation.features.processInputs()</code> 222 - </div> 223 - </li> 224 - <li> 225 - <span>Search through your collection</span> 226 - <div class="list-description" style="margin-bottom: 0;"> 227 - <code>foundation.features.searchThroughCollection()</code> 228 - </div> 229 - </li> 230 - </ul> 231 - </section> 232 - 233 - <section class="flex"> 234 - <h2 id="examples">Examples</h2> 235 - 236 - <p> 237 - Some simple examples to help you understand how to build your own facet. Fork them to load them into the code editor below (or save → edit). 238 - </p> 239 - 240 - {{ await comp.facets.list({ id: "examples", items: examples }) }} 241 - 242 - <h2 id="notes">Notes</h2> 243 - <p> 244 - While you have the ability to do whatever you want in a custom facet, the existing facets are designed to work a certain way; so here's some things to keep in mind: 245 - </p> 246 - <ul> 247 - <li><span>In most cases you'll want to call <code>foundation.features.processInputs()</code> so that your audio files and streams actually show up.</span></li> 248 - <li><span>Most elements are configured in broadcast mode so they communicate across tabs. There are a few exceptions such as inputs, where we prefer parallelisation.</span></li> 249 - <li><span>You can use facets in combination with themes by adding the elements used in the theme to a group and then passing in the group name as a URL query parameter (eg. <code>group=facets</code>)</span></li> 250 - </ul> 251 - </section> 252 - </div> 253 - </main>
···
+137 -2
src/facets/build.vto
··· 2 layout: layouts/facets.vto 3 base: ../../ 4 title: Build | Facets | Diffuse 5 --- 6 7 - <section> 8 - <h1 hidden>Build</h1> 9 </section>
··· 2 layout: layouts/facets.vto 3 base: ../../ 4 title: Build | Facets | Diffuse 5 + 6 + styles: 7 + - styles/base.css 8 + - styles/diffuse/page.css 9 + - styles/diffuse/code-editor.css 10 + - vendor/@phosphor-icons/bold/style.css 11 + - vendor/@phosphor-icons/fill/style.css 12 + 13 + scripts: 14 + - facets/build.js 15 + 16 + examples: 17 + - url: "facets/examples/now-playing/index.html" 18 + title: "Now playing" 19 + desc: > 20 + Shows what's currently set to "now playing" in the queue, along with a button to shift the queue to the next track. 21 + - url: "facets/examples/generate-playlist/index.html" 22 + title: "Generate playlist" 23 + desc: > 24 + Make a list of what previously played in the queue. 25 --- 26 27 + <h1 id="build" hidden>Build</h1> 28 + 29 + 30 + <!-- BUILD --> 31 + <section style="margin-top: var(--space-lg);"> 32 + <form id="build-form" class="columns"> 33 + <div class="flex"> 34 + <div id="html-input-container" class="code-editor monospace-font"> 35 + </div> 36 + </div> 37 + 38 + <div style="flex: 1; max-width: var(--container-sm)"> 39 + <p style="margin-top: 0"> 40 + Your code here builds on the <a href="#foundation">foundation</a> listed below, and will be injected into a <span style="white-space: nowrap"><code>&lt;div id="container"&gt;</code></span> element in the body. 41 + </p> 42 + <p> 43 + <input id="name-input" type="text" placeholder="Name" name="name" required /> 44 + </p> 45 + <p> 46 + <textarea id="description-input" placeholder="Description" name="description" rows="5"></textarea> 47 + </p> 48 + <p> 49 + <span class="button-row"> 50 + <button class="button--bg-twist-2" name="save">Save</button> 51 + <button class="button--bg-twist-2" name="save+open">Save &amp; Open</button> 52 + </span> 53 + </p> 54 + </div> 55 + </form> 56 </section> 57 + 58 + <!-- FOUNDATION --> 59 + <div class="columns"> 60 + <section class="flex"> 61 + <h2 id="foundation">Foundation</h2> 62 + 63 + <p> 64 + Diffuse comes with a foundation that preconfigures all elements so you don't have to set them up yourself, along with a combination of elements for certain features. It internally tracks the DOM addition of the custom elements, so no need to worry about setting up an element multiple times. 65 + </p> 66 + <p> 67 + <small><i class="ph-fill ph-info"></i> Refer to the <a href="#elements">elements index</a> to find out what each element does.</small> 68 + </p> 69 + <div class="code-block"> 70 + <code> 71 + {{- echo -}} 72 + import foundation from "common/facets/foundation.js" 73 + {{ /echo }} 74 + {{ echo -}}foundation.engine.audio(){{- /echo }} 75 + {{ echo -}}foundation.engine.queue(){{- /echo }} 76 + {{ echo -}}foundation.engine.repeatShuffle(){{- /echo }} 77 + {{ echo -}}foundation.engine.scope(){{- /echo }} 78 + 79 + {{ echo -}}foundation.orchestrator.autoQueue(){{- /echo }} 80 + {{ echo -}}foundation.orchestrator.favourites(){{- /echo }} 81 + {{ echo -}}foundation.orchestrator.input(){{- /echo }} 82 + {{ echo -}}foundation.orchestrator.output(){{- /echo }} 83 + {{ echo -}}foundation.orchestrator.queueAudio(){{- /echo }} 84 + {{ echo -}}foundation.orchestrator.processTracks(){{- /echo }} 85 + {{ echo -}}foundation.orchestrator.scopedTracks(){{- /echo }} 86 + {{ echo -}}foundation.orchestrator.sources(){{- /echo }} 87 + 88 + {{ echo -}}foundation.processor.artwork(){{- /echo }} 89 + {{ echo -}}foundation.processor.metadata(){{- /echo }} 90 + {{ echo -}}foundation.processor.search(){{- /echo -}} 91 + </code> 92 + </div> 93 + 94 + <p> 95 + <small>Features:</small> 96 + </p> 97 + <ul style="margin-bottom: 0;"> 98 + <li> 99 + <span>Fill the queue automatically <small>(infinite play)</small></span> 100 + <div class="list-description"> 101 + <code>foundation.features.fillQueueAutomatically()</code> 102 + </div> 103 + </li> 104 + <li> 105 + <span>Play audio from the queue</span> 106 + <div class="list-description"> 107 + <code>foundation.features.playAudioFromQueue()</code> 108 + </div> 109 + </li> 110 + <li> 111 + <span>Process inputs <small>(into tracks, etc)</small></span> 112 + <div class="list-description"> 113 + <code>foundation.features.processInputs()</code> 114 + </div> 115 + </li> 116 + <li> 117 + <span>Search through your collection</span> 118 + <div class="list-description" style="margin-bottom: 0;"> 119 + <code>foundation.features.searchThroughCollection()</code> 120 + </div> 121 + </li> 122 + </ul> 123 + </section> 124 + 125 + <section class="flex"> 126 + <h2 id="examples">Examples</h2> 127 + 128 + <p> 129 + Some simple examples to help you understand how to build your own facet. Click the edit button to load them into the code editor above. 130 + </p> 131 + 132 + {{ await comp.facets.examples({ id: "examples", items: examples }) }} 133 + 134 + <h2 id="notes">Notes</h2> 135 + <p> 136 + While you have the ability to do whatever you want in a custom facet, the existing facets are designed to work a certain way; so here's some things to keep in mind: 137 + </p> 138 + <ul> 139 + <li><span>In most cases you'll want to call <code>foundation.features.processInputs()</code> so that your audio files and streams actually show up.</span></li> 140 + <li><span>Most elements are configured in broadcast mode so they communicate across tabs. There are a few exceptions such as inputs, where we prefer parallelisation.</span></li> 141 + <li><span>You can use facets in combination with themes by adding the elements used in the theme to a group and then passing in the group name as a URL query parameter (eg. <code>group=facets</code>)</span></li> 142 + </ul> 143 + </section> 144 + </div>
+1 -1
src/facets/index.vto
··· 10 {{ await comp.facets.grid({ id: "featured", items: facets.filter(f => f.featured) }) }} 11 </section> 12 13 - <script src="facets/pages/grid-toggle.js" type="module"></script>
··· 10 {{ await comp.facets.grid({ id: "featured", items: facets.filter(f => f.featured) }) }} 11 </section> 12 13 + <script src="facets/common/grid-toggle.js" type="module"></script>
src/facets/pages/grid-toggle.js src/facets/common/grid-toggle.js
-51
src/facets/pages/save-fork.js
··· 1 - import * as Output from "~/common/output.js"; 2 - import foundation from "~/common/facets/foundation.js"; 3 - import { facetFromURI } from "~/common/facets/utils.js"; 4 - 5 - //////////////////////////////////////////// 6 - // SAVE & FORK 7 - //////////////////////////////////////////// 8 - 9 - document.body.addEventListener( 10 - "click", 11 - /** 12 - * @param {MouseEvent} event 13 - */ 14 - async (event) => { 15 - const target = /** @type {HTMLElement} */ (event.target); 16 - const rel = target.getAttribute("rel"); 17 - if (!rel) return; 18 - 19 - const uri = target.closest("li")?.getAttribute("data-uri"); 20 - if (!uri) return; 21 - 22 - const name = target.closest("li")?.getAttribute("data-name"); 23 - if (!name) return; 24 - 25 - switch (rel) { 26 - case "fork": { 27 - // TODO: Go to build page and load this facet into the editor. 28 - // 29 - // const facet = await facetFromURI({ name, uri }, { fetchHTML: true }); 30 - // editFacet(facet); 31 - // document.querySelector("#build")?.scrollIntoView(); 32 - break; 33 - } 34 - case "save": { 35 - const facet = await facetFromURI({ name, uri }, { fetchHTML: false }); 36 - const out = foundation.orchestrator.output(); 37 - 38 - await Output.waitUntilLoaded(out.facets); 39 - 40 - out.facets.save([ 41 - ...out.facets.collection(), 42 - facet, 43 - ]); 44 - break; 45 - } 46 - } 47 - 48 - // @ts-ignore No types exist yet for this I think? 49 - target.closest("[popover]")?.hidePopover(); 50 - }, 51 - );
···
+4 -4
src/styles/diffuse/code-editor.css
··· 1 .code-editor { 2 font-size: var(--fs-sm); 3 - font-size: calc((var(--fs-xs) + var(--fs-sm)) / 2); 4 - height: var(--container-xs); 5 } 6 7 .code-editor .cm-editor { ··· 23 border: 0; 24 color: oklch(from var(--text-color) l c h / 0.375); 25 font-size: var(--fs-xs); 26 - line-height: 20px; 27 } 28 29 .cm-activeLineGutter { 30 - background: var(--accent); 31 color: var(--bg-color); 32 } 33
··· 1 .code-editor { 2 font-size: var(--fs-sm); 3 + /*font-size: calc((var(--fs-xs) + var(--fs-sm)) / 2);*/ 4 + height: var(--container-md); 5 } 6 7 .code-editor .cm-editor { ··· 23 border: 0; 24 color: oklch(from var(--text-color) l c h / 0.375); 25 font-size: var(--fs-xs); 26 + line-height: calc(var(--fs-xs) * 1.9); 27 } 28 29 .cm-activeLineGutter { 30 + background: var(--accent-twist-2); 31 color: var(--bg-color); 32 } 33
+1 -3
src/styles/diffuse/page.css
··· 203 } 204 205 textarea { 206 - height: var(--container-xs); 207 padding: var(--space-xs); 208 resize: none; 209 } ··· 388 &.button--small { 389 font-size: var(--fs-xs); 390 line-height: 1; 391 - padding: var(--space-3xs); 392 - border-radius: var(--radius-xs); 393 } 394 395 &.button--subtle {
··· 203 } 204 205 textarea { 206 padding: var(--space-xs); 207 resize: none; 208 } ··· 387 &.button--small { 388 font-size: var(--fs-xs); 389 line-height: 1; 390 + padding: var(--space-3xs) var(--space-2xs); 391 } 392 393 &.button--subtle {