mirror of
https://github.com/onsonr/nebula.git
synced 2025-03-10 17:29:11 +00:00
feat: add passkey component
This commit is contained in:
parent
d8b4ee852a
commit
b6b4c38dfc
12
Taskfile.yml
Normal file
12
Taskfile.yml
Normal file
@ -0,0 +1,12 @@
|
|||||||
|
# https://taskfile.dev
|
||||||
|
|
||||||
|
version: '3'
|
||||||
|
|
||||||
|
vars:
|
||||||
|
GREETING: Hello, World!
|
||||||
|
|
||||||
|
tasks:
|
||||||
|
templ:
|
||||||
|
cmds:
|
||||||
|
- templ generate
|
||||||
|
silent: true
|
22
docs/pages/components/passkey.md
Normal file
22
docs/pages/components/passkey.md
Normal file
@ -0,0 +1,22 @@
|
|||||||
|
---
|
||||||
|
meta:
|
||||||
|
title: Passkey
|
||||||
|
description:
|
||||||
|
layout: component
|
||||||
|
---
|
||||||
|
|
||||||
|
```html:preview
|
||||||
|
<sl-passkey></sl-passkey>
|
||||||
|
```
|
||||||
|
|
||||||
|
## Examples
|
||||||
|
|
||||||
|
### First Example
|
||||||
|
|
||||||
|
TODO
|
||||||
|
|
||||||
|
### Second Example
|
||||||
|
|
||||||
|
TODO
|
||||||
|
|
||||||
|
[component-metadata:sl-passkey]
|
43
src/components/passkey/passkey.component.ts
Normal file
43
src/components/passkey/passkey.component.ts
Normal file
@ -0,0 +1,43 @@
|
|||||||
|
import { property } from 'lit/decorators.js';
|
||||||
|
import { html } from 'lit';
|
||||||
|
import { LocalizeController } from '../../utilities/localize.js';
|
||||||
|
import { watch } from '../../internal/watch.js';
|
||||||
|
import componentStyles from '../../styles/component.styles.js';
|
||||||
|
import ShoelaceElement from '../../internal/shoelace-element.js';
|
||||||
|
import styles from './passkey.styles.js';
|
||||||
|
import type { CSSResultGroup } from 'lit';
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @summary Short summary of the component's intended use.
|
||||||
|
* @documentation https://shoelace.style/components/passkey
|
||||||
|
* @status experimental
|
||||||
|
* @since 2.0
|
||||||
|
*
|
||||||
|
* @dependency sl-example
|
||||||
|
*
|
||||||
|
* @event sl-event-name - Emitted as an example.
|
||||||
|
*
|
||||||
|
* @slot - The default slot.
|
||||||
|
* @slot example - An example slot.
|
||||||
|
*
|
||||||
|
* @csspart base - The component's base wrapper.
|
||||||
|
*
|
||||||
|
* @cssproperty --example - An example CSS custom property.
|
||||||
|
*/
|
||||||
|
export default class SlPasskey extends ShoelaceElement {
|
||||||
|
static styles: CSSResultGroup = [componentStyles, styles];
|
||||||
|
|
||||||
|
private readonly localize = new LocalizeController(this);
|
||||||
|
|
||||||
|
/** An example attribute. */
|
||||||
|
@property() attr = 'example';
|
||||||
|
|
||||||
|
@watch('example')
|
||||||
|
handleExampleChange() {
|
||||||
|
// do something
|
||||||
|
}
|
||||||
|
|
||||||
|
render() {
|
||||||
|
return html` <slot></slot> `;
|
||||||
|
}
|
||||||
|
}
|
7
src/components/passkey/passkey.styles.ts
Normal file
7
src/components/passkey/passkey.styles.ts
Normal file
@ -0,0 +1,7 @@
|
|||||||
|
import { css } from 'lit';
|
||||||
|
|
||||||
|
export default css`
|
||||||
|
:host {
|
||||||
|
display: block;
|
||||||
|
}
|
||||||
|
`;
|
10
src/components/passkey/passkey.test.ts
Normal file
10
src/components/passkey/passkey.test.ts
Normal file
@ -0,0 +1,10 @@
|
|||||||
|
import '../../../dist/shoelace.js';
|
||||||
|
import { expect, fixture, html } from '@open-wc/testing';
|
||||||
|
|
||||||
|
describe('<sl-passkey>', () => {
|
||||||
|
it('should render a component', async () => {
|
||||||
|
const el = await fixture(html` <sl-passkey></sl-passkey> `);
|
||||||
|
|
||||||
|
expect(el).to.exist;
|
||||||
|
});
|
||||||
|
});
|
12
src/components/passkey/passkey.ts
Normal file
12
src/components/passkey/passkey.ts
Normal file
@ -0,0 +1,12 @@
|
|||||||
|
import SlPasskey from './passkey.component.js';
|
||||||
|
|
||||||
|
export * from './passkey.component.js';
|
||||||
|
export default SlPasskey;
|
||||||
|
|
||||||
|
SlPasskey.define('sl-passkey');
|
||||||
|
|
||||||
|
declare global {
|
||||||
|
interface HTMLElementTagNameMap {
|
||||||
|
'sl-passkey': SlPasskey;
|
||||||
|
}
|
||||||
|
}
|
@ -57,6 +57,7 @@ export { default as SlTooltip } from './components/tooltip/tooltip.js';
|
|||||||
export { default as SlTree } from './components/tree/tree.js';
|
export { default as SlTree } from './components/tree/tree.js';
|
||||||
export { default as SlTreeItem } from './components/tree-item/tree-item.js';
|
export { default as SlTreeItem } from './components/tree-item/tree-item.js';
|
||||||
export { default as SlVisuallyHidden } from './components/visually-hidden/visually-hidden.js';
|
export { default as SlVisuallyHidden } from './components/visually-hidden/visually-hidden.js';
|
||||||
|
export { default as SlPasskey } from './components/passkey/passkey.js';
|
||||||
/* plop:component */
|
/* plop:component */
|
||||||
|
|
||||||
// Utilities
|
// Utilities
|
||||||
|
@ -1,15 +0,0 @@
|
|||||||
package button
|
|
||||||
|
|
||||||
templ Primary(href string, text string) {
|
|
||||||
<div>
|
|
||||||
<div class="btn cursor-pointer text-zinc-100 bg-zinc-900 hover:bg-zinc-800 w-full shadow" hx-swap="afterend" hx-get={ href }>
|
|
||||||
{ text }
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
}
|
|
||||||
|
|
||||||
templ Secondary(href string, text string) {
|
|
||||||
<div>
|
|
||||||
<div x-on:click="toast('Default Toast Notification', 'default', '', 'top-center')" class="btn cursor-pointer text-zinc-600 bg-white hover:text-zinc-900 w-full shadow">{ text }</div>
|
|
||||||
</div>
|
|
||||||
}
|
|
@ -1,108 +0,0 @@
|
|||||||
// Code generated by templ - DO NOT EDIT.
|
|
||||||
|
|
||||||
// templ: version: v0.2.793
|
|
||||||
package button
|
|
||||||
|
|
||||||
//lint:file-ignore SA4006 This context is only used if a nested component is present.
|
|
||||||
|
|
||||||
import "github.com/a-h/templ"
|
|
||||||
import templruntime "github.com/a-h/templ/runtime"
|
|
||||||
|
|
||||||
func Primary(href string, text string) templ.Component {
|
|
||||||
return templruntime.GeneratedTemplate(func(templ_7745c5c3_Input templruntime.GeneratedComponentInput) (templ_7745c5c3_Err error) {
|
|
||||||
templ_7745c5c3_W, ctx := templ_7745c5c3_Input.Writer, templ_7745c5c3_Input.Context
|
|
||||||
if templ_7745c5c3_CtxErr := ctx.Err(); templ_7745c5c3_CtxErr != nil {
|
|
||||||
return templ_7745c5c3_CtxErr
|
|
||||||
}
|
|
||||||
templ_7745c5c3_Buffer, templ_7745c5c3_IsBuffer := templruntime.GetBuffer(templ_7745c5c3_W)
|
|
||||||
if !templ_7745c5c3_IsBuffer {
|
|
||||||
defer func() {
|
|
||||||
templ_7745c5c3_BufErr := templruntime.ReleaseBuffer(templ_7745c5c3_Buffer)
|
|
||||||
if templ_7745c5c3_Err == nil {
|
|
||||||
templ_7745c5c3_Err = templ_7745c5c3_BufErr
|
|
||||||
}
|
|
||||||
}()
|
|
||||||
}
|
|
||||||
ctx = templ.InitializeContext(ctx)
|
|
||||||
templ_7745c5c3_Var1 := templ.GetChildren(ctx)
|
|
||||||
if templ_7745c5c3_Var1 == nil {
|
|
||||||
templ_7745c5c3_Var1 = templ.NopComponent
|
|
||||||
}
|
|
||||||
ctx = templ.ClearChildren(ctx)
|
|
||||||
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("<div><div class=\"btn cursor-pointer text-zinc-100 bg-zinc-900 hover:bg-zinc-800 w-full shadow\" hx-swap=\"afterend\" hx-get=\"")
|
|
||||||
if templ_7745c5c3_Err != nil {
|
|
||||||
return templ_7745c5c3_Err
|
|
||||||
}
|
|
||||||
var templ_7745c5c3_Var2 string
|
|
||||||
templ_7745c5c3_Var2, templ_7745c5c3_Err = templ.JoinStringErrs(href)
|
|
||||||
if templ_7745c5c3_Err != nil {
|
|
||||||
return templ.Error{Err: templ_7745c5c3_Err, FileName: `ui/button/default.templ`, Line: 5, Col: 124}
|
|
||||||
}
|
|
||||||
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var2))
|
|
||||||
if templ_7745c5c3_Err != nil {
|
|
||||||
return templ_7745c5c3_Err
|
|
||||||
}
|
|
||||||
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("\">")
|
|
||||||
if templ_7745c5c3_Err != nil {
|
|
||||||
return templ_7745c5c3_Err
|
|
||||||
}
|
|
||||||
var templ_7745c5c3_Var3 string
|
|
||||||
templ_7745c5c3_Var3, templ_7745c5c3_Err = templ.JoinStringErrs(text)
|
|
||||||
if templ_7745c5c3_Err != nil {
|
|
||||||
return templ.Error{Err: templ_7745c5c3_Err, FileName: `ui/button/default.templ`, Line: 6, Col: 9}
|
|
||||||
}
|
|
||||||
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var3))
|
|
||||||
if templ_7745c5c3_Err != nil {
|
|
||||||
return templ_7745c5c3_Err
|
|
||||||
}
|
|
||||||
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("</div></div>")
|
|
||||||
if templ_7745c5c3_Err != nil {
|
|
||||||
return templ_7745c5c3_Err
|
|
||||||
}
|
|
||||||
return templ_7745c5c3_Err
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
func Secondary(href string, text string) templ.Component {
|
|
||||||
return templruntime.GeneratedTemplate(func(templ_7745c5c3_Input templruntime.GeneratedComponentInput) (templ_7745c5c3_Err error) {
|
|
||||||
templ_7745c5c3_W, ctx := templ_7745c5c3_Input.Writer, templ_7745c5c3_Input.Context
|
|
||||||
if templ_7745c5c3_CtxErr := ctx.Err(); templ_7745c5c3_CtxErr != nil {
|
|
||||||
return templ_7745c5c3_CtxErr
|
|
||||||
}
|
|
||||||
templ_7745c5c3_Buffer, templ_7745c5c3_IsBuffer := templruntime.GetBuffer(templ_7745c5c3_W)
|
|
||||||
if !templ_7745c5c3_IsBuffer {
|
|
||||||
defer func() {
|
|
||||||
templ_7745c5c3_BufErr := templruntime.ReleaseBuffer(templ_7745c5c3_Buffer)
|
|
||||||
if templ_7745c5c3_Err == nil {
|
|
||||||
templ_7745c5c3_Err = templ_7745c5c3_BufErr
|
|
||||||
}
|
|
||||||
}()
|
|
||||||
}
|
|
||||||
ctx = templ.InitializeContext(ctx)
|
|
||||||
templ_7745c5c3_Var4 := templ.GetChildren(ctx)
|
|
||||||
if templ_7745c5c3_Var4 == nil {
|
|
||||||
templ_7745c5c3_Var4 = templ.NopComponent
|
|
||||||
}
|
|
||||||
ctx = templ.ClearChildren(ctx)
|
|
||||||
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("<div><div x-on:click=\"toast('Default Toast Notification', 'default', '', 'top-center')\" class=\"btn cursor-pointer text-zinc-600 bg-white hover:text-zinc-900 w-full shadow\">")
|
|
||||||
if templ_7745c5c3_Err != nil {
|
|
||||||
return templ_7745c5c3_Err
|
|
||||||
}
|
|
||||||
var templ_7745c5c3_Var5 string
|
|
||||||
templ_7745c5c3_Var5, templ_7745c5c3_Err = templ.JoinStringErrs(text)
|
|
||||||
if templ_7745c5c3_Err != nil {
|
|
||||||
return templ.Error{Err: templ_7745c5c3_Err, FileName: `ui/button/default.templ`, Line: 13, Col: 175}
|
|
||||||
}
|
|
||||||
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var5))
|
|
||||||
if templ_7745c5c3_Err != nil {
|
|
||||||
return templ_7745c5c3_Err
|
|
||||||
}
|
|
||||||
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("</div></div>")
|
|
||||||
if templ_7745c5c3_Err != nil {
|
|
||||||
return templ_7745c5c3_Err
|
|
||||||
}
|
|
||||||
return templ_7745c5c3_Err
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
var _ = templruntime.GeneratedTemplate
|
|
@ -1,175 +0,0 @@
|
|||||||
package form
|
|
||||||
|
|
||||||
import "github.com/go-webauthn/webauthn/protocol"
|
|
||||||
|
|
||||||
var credentialsHandle = templ.NewOnceHandle()
|
|
||||||
|
|
||||||
// Base credentials script template
|
|
||||||
templ CredentialsScripts() {
|
|
||||||
@credentialsHandle.Once() {
|
|
||||||
<script type="text/javascript">
|
|
||||||
// Check if WebAuthn is supported
|
|
||||||
async function isWebAuthnSupported() {
|
|
||||||
return window.PublicKeyCredential !== undefined;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Create credentials
|
|
||||||
async function createCredential(options) {
|
|
||||||
try {
|
|
||||||
const publicKey = {
|
|
||||||
challenge: base64URLDecode(options.challenge),
|
|
||||||
rp: {
|
|
||||||
name: options.rpName,
|
|
||||||
id: options.rpId,
|
|
||||||
},
|
|
||||||
user: {
|
|
||||||
id: base64URLDecode(options.userId),
|
|
||||||
name: options.userName,
|
|
||||||
displayName: options.userDisplayName,
|
|
||||||
},
|
|
||||||
pubKeyCredParams: [{alg: -7, type: "public-key"}],
|
|
||||||
timeout: options.timeout || 60000,
|
|
||||||
attestation: options.attestationType || "none",
|
|
||||||
};
|
|
||||||
|
|
||||||
const credential = await navigator.credentials.create({
|
|
||||||
publicKey: publicKey
|
|
||||||
});
|
|
||||||
|
|
||||||
return {
|
|
||||||
id: credential.id,
|
|
||||||
rawId: arrayBufferToBase64URL(credential.rawId),
|
|
||||||
type: credential.type,
|
|
||||||
response: {
|
|
||||||
attestationObject: arrayBufferToBase64URL(credential.response.attestationObject),
|
|
||||||
clientDataJSON: arrayBufferToBase64URL(credential.response.clientDataJSON),
|
|
||||||
}
|
|
||||||
};
|
|
||||||
} catch (err) {
|
|
||||||
console.error('Error creating credential:', err);
|
|
||||||
throw err;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Get credentials
|
|
||||||
async function getCredential(options) {
|
|
||||||
try {
|
|
||||||
const publicKey = {
|
|
||||||
challenge: base64URLDecode(options.challenge),
|
|
||||||
rpId: options.rpId,
|
|
||||||
timeout: options.timeout || 60000,
|
|
||||||
userVerification: options.userVerification || "preferred",
|
|
||||||
};
|
|
||||||
|
|
||||||
if (options.allowCredentials) {
|
|
||||||
publicKey.allowCredentials = options.allowCredentials.map(cred => ({
|
|
||||||
type: cred.type,
|
|
||||||
id: base64URLDecode(cred.id),
|
|
||||||
}));
|
|
||||||
}
|
|
||||||
|
|
||||||
const assertion = await navigator.credentials.get({
|
|
||||||
publicKey: publicKey
|
|
||||||
});
|
|
||||||
|
|
||||||
return {
|
|
||||||
id: assertion.id,
|
|
||||||
rawId: arrayBufferToBase64URL(assertion.rawId),
|
|
||||||
type: assertion.type,
|
|
||||||
response: {
|
|
||||||
authenticatorData: arrayBufferToBase64URL(assertion.response.authenticatorData),
|
|
||||||
clientDataJSON: arrayBufferToBase64URL(assertion.response.clientDataJSON),
|
|
||||||
signature: arrayBufferToBase64URL(assertion.response.signature),
|
|
||||||
userHandle: assertion.response.userHandle ? arrayBufferToBase64URL(assertion.response.userHandle) : null
|
|
||||||
}
|
|
||||||
};
|
|
||||||
} catch (err) {
|
|
||||||
console.error('Error getting credential:', err);
|
|
||||||
throw err;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Utility functions for base64URL encoding/decoding
|
|
||||||
function base64URLDecode(base64url) {
|
|
||||||
const padding = '='.repeat((4 - base64url.length % 4) % 4);
|
|
||||||
const base64 = (base64url + padding)
|
|
||||||
.replace(/\-/g, '+')
|
|
||||||
.replace(/_/g, '/');
|
|
||||||
const rawData = window.atob(base64);
|
|
||||||
const array = new Uint8Array(rawData.length);
|
|
||||||
for (let i = 0; i < rawData.length; i++) {
|
|
||||||
array[i] = rawData.charCodeAt(i);
|
|
||||||
}
|
|
||||||
return array.buffer;
|
|
||||||
}
|
|
||||||
|
|
||||||
function arrayBufferToBase64URL(buffer) {
|
|
||||||
let binary = '';
|
|
||||||
const bytes = new Uint8Array(buffer);
|
|
||||||
for (let i = 0; i < bytes.byteLength; i++) {
|
|
||||||
binary += String.fromCharCode(bytes[i]);
|
|
||||||
}
|
|
||||||
const base64 = window.btoa(binary);
|
|
||||||
return base64
|
|
||||||
.replace(/\+/g, '-')
|
|
||||||
.replace(/\//g, '_')
|
|
||||||
.replace(/=/g, '');
|
|
||||||
}
|
|
||||||
</script>
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
script CreatePasskey(id string) {
|
|
||||||
function createPasskey(id) {
|
|
||||||
const passkey = document.getElementById(id);
|
|
||||||
passkey.value = window.crypto.getRandomValues(new Uint8Array(32)).join('');
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Template for creating credentials
|
|
||||||
templ CreateCredential(options *protocol.PublicKeyCredentialCreationOptions) {
|
|
||||||
@CredentialsScripts()
|
|
||||||
<script>
|
|
||||||
(async () => {
|
|
||||||
try {
|
|
||||||
if (!await isWebAuthnSupported()) {
|
|
||||||
throw new Error("WebAuthn is not supported in this browser");
|
|
||||||
}
|
|
||||||
const options = { templ.JSONString(options) };
|
|
||||||
const credential = await createCredential(options);
|
|
||||||
// Dispatch event with credential data
|
|
||||||
window.dispatchEvent(new CustomEvent('credentialCreated', {
|
|
||||||
detail: credential
|
|
||||||
}));
|
|
||||||
} catch (err) {
|
|
||||||
window.dispatchEvent(new CustomEvent('credentialError', {
|
|
||||||
detail: err.message
|
|
||||||
}));
|
|
||||||
}
|
|
||||||
})();
|
|
||||||
</script>
|
|
||||||
}
|
|
||||||
|
|
||||||
// Template for getting credentials
|
|
||||||
templ GetCredential(options *protocol.PublicKeyCredentialRequestOptions) {
|
|
||||||
@CredentialsScripts()
|
|
||||||
<script>
|
|
||||||
(async () => {
|
|
||||||
try {
|
|
||||||
if (!await isWebAuthnSupported()) {
|
|
||||||
throw new Error("WebAuthn is not supported in this browser");
|
|
||||||
}
|
|
||||||
const options = { templ.JSONString(options) };
|
|
||||||
const credential = await getCredential(options);
|
|
||||||
// Dispatch event with credential data
|
|
||||||
window.dispatchEvent(new CustomEvent('credentialRetrieved', {
|
|
||||||
detail: credential
|
|
||||||
}));
|
|
||||||
} catch (err) {
|
|
||||||
window.dispatchEvent(new CustomEvent('credentialError', {
|
|
||||||
detail: err.message
|
|
||||||
}));
|
|
||||||
}
|
|
||||||
})();
|
|
||||||
</script>
|
|
||||||
}
|
|
@ -160,7 +160,7 @@ func Alpine() templ.Component {
|
|||||||
var templ_7745c5c3_Var7 string
|
var templ_7745c5c3_Var7 string
|
||||||
templ_7745c5c3_Var7, templ_7745c5c3_Err = templ.JoinStringErrs(jsDelivrURL("alpinejs", "3.14.6", "dist/cdn.min.js"))
|
templ_7745c5c3_Var7, templ_7745c5c3_Err = templ.JoinStringErrs(jsDelivrURL("alpinejs", "3.14.6", "dist/cdn.min.js"))
|
||||||
if templ_7745c5c3_Err != nil {
|
if templ_7745c5c3_Err != nil {
|
||||||
return templ.Error{Err: templ_7745c5c3_Err, FileName: `ui/layout/scripts.templ`, Line: 36, Col: 68}
|
return templ.Error{Err: templ_7745c5c3_Err, FileName: `ui/layout/imports.templ`, Line: 36, Col: 68}
|
||||||
}
|
}
|
||||||
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var7))
|
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var7))
|
||||||
if templ_7745c5c3_Err != nil {
|
if templ_7745c5c3_Err != nil {
|
||||||
@ -173,7 +173,7 @@ func Alpine() templ.Component {
|
|||||||
var templ_7745c5c3_Var8 string
|
var templ_7745c5c3_Var8 string
|
||||||
templ_7745c5c3_Var8, templ_7745c5c3_Err = templ.JoinStringErrs(jsDelivrURL("@alpinejs/focus", "3.14.6", "dist/cdn.min.js"))
|
templ_7745c5c3_Var8, templ_7745c5c3_Err = templ.JoinStringErrs(jsDelivrURL("@alpinejs/focus", "3.14.6", "dist/cdn.min.js"))
|
||||||
if templ_7745c5c3_Err != nil {
|
if templ_7745c5c3_Err != nil {
|
||||||
return templ.Error{Err: templ_7745c5c3_Err, FileName: `ui/layout/scripts.templ`, Line: 37, Col: 75}
|
return templ.Error{Err: templ_7745c5c3_Err, FileName: `ui/layout/imports.templ`, Line: 37, Col: 75}
|
||||||
}
|
}
|
||||||
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var8))
|
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var8))
|
||||||
if templ_7745c5c3_Err != nil {
|
if templ_7745c5c3_Err != nil {
|
||||||
@ -234,7 +234,7 @@ func Dexie() templ.Component {
|
|||||||
var templ_7745c5c3_Var11 string
|
var templ_7745c5c3_Var11 string
|
||||||
templ_7745c5c3_Var11, templ_7745c5c3_Err = templ.JoinStringErrs(jsDelivrURL("dexie", "4.0.10", "dist/dexie.min.js"))
|
templ_7745c5c3_Var11, templ_7745c5c3_Err = templ.JoinStringErrs(jsDelivrURL("dexie", "4.0.10", "dist/dexie.min.js"))
|
||||||
if templ_7745c5c3_Err != nil {
|
if templ_7745c5c3_Err != nil {
|
||||||
return templ.Error{Err: templ_7745c5c3_Err, FileName: `ui/layout/scripts.templ`, Line: 44, Col: 67}
|
return templ.Error{Err: templ_7745c5c3_Err, FileName: `ui/layout/imports.templ`, Line: 44, Col: 67}
|
||||||
}
|
}
|
||||||
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var11))
|
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var11))
|
||||||
if templ_7745c5c3_Err != nil {
|
if templ_7745c5c3_Err != nil {
|
||||||
@ -247,7 +247,7 @@ func Dexie() templ.Component {
|
|||||||
var templ_7745c5c3_Var12 string
|
var templ_7745c5c3_Var12 string
|
||||||
templ_7745c5c3_Var12, templ_7745c5c3_Err = templ.JoinStringErrs(jsDelivrURL("dexie-export-import", "4.1.4", "dist/dexie-export-import.min.js"))
|
templ_7745c5c3_Var12, templ_7745c5c3_Err = templ.JoinStringErrs(jsDelivrURL("dexie-export-import", "4.1.4", "dist/dexie-export-import.min.js"))
|
||||||
if templ_7745c5c3_Err != nil {
|
if templ_7745c5c3_Err != nil {
|
||||||
return templ.Error{Err: templ_7745c5c3_Err, FileName: `ui/layout/scripts.templ`, Line: 45, Col: 94}
|
return templ.Error{Err: templ_7745c5c3_Err, FileName: `ui/layout/imports.templ`, Line: 45, Col: 94}
|
||||||
}
|
}
|
||||||
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var12))
|
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var12))
|
||||||
if templ_7745c5c3_Err != nil {
|
if templ_7745c5c3_Err != nil {
|
||||||
@ -308,7 +308,7 @@ func Htmx() templ.Component {
|
|||||||
var templ_7745c5c3_Var15 string
|
var templ_7745c5c3_Var15 string
|
||||||
templ_7745c5c3_Var15, templ_7745c5c3_Err = templ.JoinStringErrs(jsDelivrURL("htmx.org", "1.9.12", "dist/htmx.min.js"))
|
templ_7745c5c3_Var15, templ_7745c5c3_Err = templ.JoinStringErrs(jsDelivrURL("htmx.org", "1.9.12", "dist/htmx.min.js"))
|
||||||
if templ_7745c5c3_Err != nil {
|
if templ_7745c5c3_Err != nil {
|
||||||
return templ.Error{Err: templ_7745c5c3_Err, FileName: `ui/layout/scripts.templ`, Line: 52, Col: 69}
|
return templ.Error{Err: templ_7745c5c3_Err, FileName: `ui/layout/imports.templ`, Line: 52, Col: 69}
|
||||||
}
|
}
|
||||||
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var15))
|
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var15))
|
||||||
if templ_7745c5c3_Err != nil {
|
if templ_7745c5c3_Err != nil {
|
||||||
@ -321,7 +321,7 @@ func Htmx() templ.Component {
|
|||||||
var templ_7745c5c3_Var16 string
|
var templ_7745c5c3_Var16 string
|
||||||
templ_7745c5c3_Var16, templ_7745c5c3_Err = templ.JoinStringErrs(jsDelivrURL("htmx-ext-include-vals", "2.0.0", "include-vals.min.js"))
|
templ_7745c5c3_Var16, templ_7745c5c3_Err = templ.JoinStringErrs(jsDelivrURL("htmx-ext-include-vals", "2.0.0", "include-vals.min.js"))
|
||||||
if templ_7745c5c3_Err != nil {
|
if templ_7745c5c3_Err != nil {
|
||||||
return templ.Error{Err: templ_7745c5c3_Err, FileName: `ui/layout/scripts.templ`, Line: 53, Col: 84}
|
return templ.Error{Err: templ_7745c5c3_Err, FileName: `ui/layout/imports.templ`, Line: 53, Col: 84}
|
||||||
}
|
}
|
||||||
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var16))
|
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var16))
|
||||||
if templ_7745c5c3_Err != nil {
|
if templ_7745c5c3_Err != nil {
|
||||||
@ -334,7 +334,7 @@ func Htmx() templ.Component {
|
|||||||
var templ_7745c5c3_Var17 string
|
var templ_7745c5c3_Var17 string
|
||||||
templ_7745c5c3_Var17, templ_7745c5c3_Err = templ.JoinStringErrs(jsDelivrURL("htmx-ext-path-params", "2.0.0", "path-params.min.js"))
|
templ_7745c5c3_Var17, templ_7745c5c3_Err = templ.JoinStringErrs(jsDelivrURL("htmx-ext-path-params", "2.0.0", "path-params.min.js"))
|
||||||
if templ_7745c5c3_Err != nil {
|
if templ_7745c5c3_Err != nil {
|
||||||
return templ.Error{Err: templ_7745c5c3_Err, FileName: `ui/layout/scripts.templ`, Line: 54, Col: 82}
|
return templ.Error{Err: templ_7745c5c3_Err, FileName: `ui/layout/imports.templ`, Line: 54, Col: 82}
|
||||||
}
|
}
|
||||||
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var17))
|
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var17))
|
||||||
if templ_7745c5c3_Err != nil {
|
if templ_7745c5c3_Err != nil {
|
||||||
@ -347,7 +347,7 @@ func Htmx() templ.Component {
|
|||||||
var templ_7745c5c3_Var18 string
|
var templ_7745c5c3_Var18 string
|
||||||
templ_7745c5c3_Var18, templ_7745c5c3_Err = templ.JoinStringErrs(jsDelivrURL("htmx-ext-alpine-morph", "2.0.0", "alpine-morph.min.js"))
|
templ_7745c5c3_Var18, templ_7745c5c3_Err = templ.JoinStringErrs(jsDelivrURL("htmx-ext-alpine-morph", "2.0.0", "alpine-morph.min.js"))
|
||||||
if templ_7745c5c3_Err != nil {
|
if templ_7745c5c3_Err != nil {
|
||||||
return templ.Error{Err: templ_7745c5c3_Err, FileName: `ui/layout/scripts.templ`, Line: 55, Col: 84}
|
return templ.Error{Err: templ_7745c5c3_Err, FileName: `ui/layout/imports.templ`, Line: 55, Col: 84}
|
||||||
}
|
}
|
||||||
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var18))
|
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var18))
|
||||||
if templ_7745c5c3_Err != nil {
|
if templ_7745c5c3_Err != nil {
|
||||||
@ -396,7 +396,7 @@ func Nebula(version string) templ.Component {
|
|||||||
var templ_7745c5c3_Var20 string
|
var templ_7745c5c3_Var20 string
|
||||||
templ_7745c5c3_Var20, templ_7745c5c3_Err = templ.JoinStringErrs(jsDelivrURL("@onsonr/nebula", version, "cdn/themes/light.css"))
|
templ_7745c5c3_Var20, templ_7745c5c3_Err = templ.JoinStringErrs(jsDelivrURL("@onsonr/nebula", version, "cdn/themes/light.css"))
|
||||||
if templ_7745c5c3_Err != nil {
|
if templ_7745c5c3_Err != nil {
|
||||||
return templ.Error{Err: templ_7745c5c3_Err, FileName: `ui/layout/scripts.templ`, Line: 64, Col: 71}
|
return templ.Error{Err: templ_7745c5c3_Err, FileName: `ui/layout/imports.templ`, Line: 64, Col: 71}
|
||||||
}
|
}
|
||||||
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var20))
|
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var20))
|
||||||
if templ_7745c5c3_Err != nil {
|
if templ_7745c5c3_Err != nil {
|
||||||
@ -409,7 +409,7 @@ func Nebula(version string) templ.Component {
|
|||||||
var templ_7745c5c3_Var21 string
|
var templ_7745c5c3_Var21 string
|
||||||
templ_7745c5c3_Var21, templ_7745c5c3_Err = templ.JoinStringErrs(jsDelivrURL("@onsonr/nebula", version, "cdn/themes/dark.css"))
|
templ_7745c5c3_Var21, templ_7745c5c3_Err = templ.JoinStringErrs(jsDelivrURL("@onsonr/nebula", version, "cdn/themes/dark.css"))
|
||||||
if templ_7745c5c3_Err != nil {
|
if templ_7745c5c3_Err != nil {
|
||||||
return templ.Error{Err: templ_7745c5c3_Err, FileName: `ui/layout/scripts.templ`, Line: 69, Col: 70}
|
return templ.Error{Err: templ_7745c5c3_Err, FileName: `ui/layout/imports.templ`, Line: 69, Col: 70}
|
||||||
}
|
}
|
||||||
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var21))
|
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var21))
|
||||||
if templ_7745c5c3_Err != nil {
|
if templ_7745c5c3_Err != nil {
|
||||||
@ -438,7 +438,7 @@ func Nebula(version string) templ.Component {
|
|||||||
var templ_7745c5c3_Var23 string
|
var templ_7745c5c3_Var23 string
|
||||||
templ_7745c5c3_Var23, templ_7745c5c3_Err = templ.JoinStringErrs(jsDelivrURL("@onsonr/nebula", version, "cdn/shoelace-autoloader.js"))
|
templ_7745c5c3_Var23, templ_7745c5c3_Err = templ.JoinStringErrs(jsDelivrURL("@onsonr/nebula", version, "cdn/shoelace-autoloader.js"))
|
||||||
if templ_7745c5c3_Err != nil {
|
if templ_7745c5c3_Err != nil {
|
||||||
return templ.Error{Err: templ_7745c5c3_Err, FileName: `ui/layout/scripts.templ`, Line: 73, Col: 98}
|
return templ.Error{Err: templ_7745c5c3_Err, FileName: `ui/layout/imports.templ`, Line: 73, Col: 98}
|
||||||
}
|
}
|
||||||
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var23))
|
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var23))
|
||||||
if templ_7745c5c3_Err != nil {
|
if templ_7745c5c3_Err != nil {
|
Loading…
x
Reference in New Issue
Block a user