docs: move documentation into monorepo
35
.github/workflows/docs-deploy.yml
vendored
Normal file
@ -0,0 +1,35 @@
|
||||
name: Deploy to GitHub Pages
|
||||
|
||||
on:
|
||||
push:
|
||||
branches:
|
||||
- main
|
||||
|
||||
jobs:
|
||||
deploy:
|
||||
name: Deploy to GitHub Pages
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v2
|
||||
- uses: actions/setup-node@v3
|
||||
with:
|
||||
node-version: 18
|
||||
cache: npm
|
||||
cache-dependency-path: docs/package-lock.json
|
||||
|
||||
- name: Install dependencies
|
||||
working-directory: ./docs
|
||||
run: npm ci
|
||||
- name: Build website
|
||||
working-directory: ./docs
|
||||
run: npm run build
|
||||
|
||||
# Popular action to deploy to GitHub Pages:
|
||||
# Docs: https://github.com/peaceiris/actions-gh-pages#%EF%B8%8F-docusaurus
|
||||
- name: Deploy to GitHub Pages
|
||||
uses: peaceiris/actions-gh-pages@v3
|
||||
with:
|
||||
github_token: ${{ secrets.GITHUB_TOKEN }}
|
||||
# Build output to publish to the `gh-pages` branch:
|
||||
publish_dir: ./docs/build
|
||||
cname: docs.hanko.io
|
||||
25
.github/workflows/docs-test-deploy.yml
vendored
Normal file
@ -0,0 +1,25 @@
|
||||
name: Test deployment
|
||||
|
||||
on:
|
||||
pull_request:
|
||||
branches:
|
||||
- main
|
||||
|
||||
jobs:
|
||||
test-deploy:
|
||||
name: Test deployment
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v2
|
||||
- uses: actions/setup-node@v3
|
||||
with:
|
||||
node-version: 18
|
||||
cache: npm
|
||||
cache-dependency-path: docs/package-lock.json
|
||||
|
||||
- name: Install dependencies
|
||||
working-directory: ./docs
|
||||
run: npm ci
|
||||
- name: Test build website
|
||||
working-directory: ./docs
|
||||
run: npm run build
|
||||
@ -77,6 +77,7 @@ The Hanko project consists of
|
||||
- [hanko-elements](/elements/README.md) - A slick web component made for Hanko backend that features a polished onboarding and login experience and is highly customizable
|
||||
- [hanko-frontend-sdk](/frontend-sdk/README.md) - A client package for using the Hanko API
|
||||
- [example](/example) - The quickstart example app, showing off Hanko's strengths and acting as a reference implementation
|
||||
- [docs](/docs) - The Hanko documentation
|
||||
|
||||
# Community
|
||||
Join our [Slack community](https://www.hanko.io/community) if you have any questions about Hanko or just want to chat about passkeys, authentication, identity, or life in general. You can also [follow us on Twitter](https://twitter.com/hanko_io) or just [reach out via email](https://www.hanko.io/contact).
|
||||
|
||||
22
docs/.gitignore
vendored
Normal file
@ -0,0 +1,22 @@
|
||||
# Dependencies
|
||||
/node_modules
|
||||
|
||||
# Production
|
||||
/build
|
||||
|
||||
# Generated files
|
||||
.docusaurus
|
||||
.cache-loader
|
||||
|
||||
# Misc
|
||||
.DS_Store
|
||||
.env.local
|
||||
.env.development.local
|
||||
.env.test.local
|
||||
.env.production.local
|
||||
|
||||
npm-debug.log*
|
||||
yarn-debug.log*
|
||||
yarn-error.log*
|
||||
|
||||
.idea
|
||||
21
docs/LICENSE
Normal file
@ -0,0 +1,21 @@
|
||||
MIT License
|
||||
|
||||
Copyright (c) 2022 Hanko.io
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all
|
||||
copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
SOFTWARE.
|
||||
41
docs/README.md
Normal file
@ -0,0 +1,41 @@
|
||||
# Hanko Documentation
|
||||
|
||||
The Hanko documentation is built using [Docusaurus 2](https://docusaurus.io/), a modern static website generator.
|
||||
|
||||
### Installation
|
||||
|
||||
```
|
||||
$ npm install
|
||||
```
|
||||
|
||||
### Local Development
|
||||
|
||||
```
|
||||
$ npm run start
|
||||
```
|
||||
|
||||
This command starts a local development server and opens up a browser window. Most changes are reflected live without having to restart the server.
|
||||
|
||||
### Build
|
||||
|
||||
```
|
||||
$ npm run build
|
||||
```
|
||||
|
||||
This command generates static content into the `build` directory and can be served using any static contents hosting service.
|
||||
|
||||
## Swizzled components
|
||||
|
||||
The following components have been [swizzled](https://docusaurus.io/docs/swizzling):
|
||||
|
||||
### `DocCard`
|
||||
|
||||
- Make icons used in the DocCard customizable via `sidebar_custom_props`
|
||||
- Make description toggle-able via `sidebar_custom_props`
|
||||
|
||||
Uses the following `sidebar_custom_props`:
|
||||
|
||||
| Name | Type | Default | Description |
|
||||
|------------------------|---------|-----------------|--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
|
||||
| docCardIconName | string | undefined | Name of the icon file without file extension. Icons must be placed in `static/img/icons` folder and have an *.svg extension. Uses default images if `undefined`. |
|
||||
| docCardShowDescription | boolean | undefined/false | Whether to show the description in auto-generated link/category cards. Introduced for SEO reasons such that front-matter `description`s can be used to generate meta tags without being forced to display them in the DocCard. |
|
||||
3
docs/babel.config.js
Normal file
@ -0,0 +1,3 @@
|
||||
module.exports = {
|
||||
presets: [require.resolve('@docusaurus/core/lib/babel/preset')],
|
||||
};
|
||||
150
docs/docs/guides/angular.mdx
Normal file
@ -0,0 +1,150 @@
|
||||
---
|
||||
title: Angular + Hanko
|
||||
sidebar_label: Angular
|
||||
keywords: [angular]
|
||||
sidebar_custom_props:
|
||||
docCardIconName: angular
|
||||
---
|
||||
|
||||
import Tabs from '@theme/Tabs';
|
||||
import TabItem from '@theme/TabItem';
|
||||
|
||||
# Angular
|
||||
|
||||
In this guide you will learn how to add authentication to your Angular application using the Hanko custom element.
|
||||
|
||||
## Install dependencies
|
||||
|
||||
Install the `@teamhanko/hanko-elements` package:
|
||||
|
||||
```shell npm2yarn
|
||||
npm install @teamhanko/hanko-elements
|
||||
```
|
||||
|
||||
## Register custom element with Angular
|
||||
|
||||
Angular requires you to explicitly declare that you are using custom elements inside your Angular modules, otherwise
|
||||
it will fail during build complaining about unknown elements. To do so, import the
|
||||
[`CUSTOM_ELEMENTS_SCHEMA`](https://angular.io/api/core/CUSTOM_ELEMENTS_SCHEMA), and add it to the `schemas` in your
|
||||
module:
|
||||
|
||||
```js {1,14} title="app.module.ts" showLineNumbers
|
||||
import { NgModule, CUSTOM_ELEMENTS_SCHEMA } from '@angular/core';
|
||||
import { BrowserModule } from '@angular/platform-browser';
|
||||
import { AppComponent } from './app.component';
|
||||
|
||||
@NgModule({
|
||||
declarations: [
|
||||
AppComponent
|
||||
],
|
||||
imports: [
|
||||
BrowserModule
|
||||
],
|
||||
providers: [],
|
||||
bootstrap: [AppComponent],
|
||||
schemas: [CUSTOM_ELEMENTS_SCHEMA]
|
||||
})
|
||||
export class AppModule { }
|
||||
```
|
||||
|
||||
## Import & use custom element
|
||||
|
||||
Import `@teamhanko/hanko-elements/hanko-auth` in the component where you want to use the Hanko custom element.
|
||||
Doing so registers the `<hanko-auth>` element with the browser's
|
||||
[`CustomElementRegistry`](https://developer.mozilla.org/de/docs/Web/API/CustomElementRegistry). Then use the element
|
||||
in your component template:
|
||||
|
||||
```mdx-code-block
|
||||
<Tabs>
|
||||
<TabItem value="html" label="login.component.html">
|
||||
```
|
||||
|
||||
```html title="login.component.html" showLineNumbers
|
||||
<hanko-auth [api]="hankoApi" [lang]="hankoLang"></hanko-auth>
|
||||
```
|
||||
|
||||
```mdx-code-block
|
||||
</TabItem>
|
||||
<TabItem value="ts" label="login.component.ts">
|
||||
```
|
||||
|
||||
```js {3,11-12} title="login.component.ts" showLineNumbers
|
||||
import { Component } from '@angular/core';
|
||||
import { environment } from '../../../environments/environment';
|
||||
import '@teamhanko/hanko-elements/hanko-auth';
|
||||
|
||||
@Component({
|
||||
selector: 'app-login',
|
||||
templateUrl: './login.component.html',
|
||||
styleUrls: ['./login.component.css']
|
||||
})
|
||||
export class LoginComponent {
|
||||
hankoApi = environment.hankoApi;
|
||||
hankoLang = environment.hankoLang;
|
||||
}
|
||||
```
|
||||
|
||||
```mdx-code-block
|
||||
</TabItem>
|
||||
</Tabs>
|
||||
```
|
||||
|
||||
|
||||
|
||||
## Defining login callbacks
|
||||
|
||||
The `<hanko-auth>` element dispatches a custom `success` event on successful login. React to this
|
||||
event in order to, for example, redirect your users to protected pages in your application.
|
||||
|
||||
To do so, you can use Angular's event binding mechanism and supply a callback function that is defined in your component
|
||||
class directly on the `<hanko-auth>` element:
|
||||
|
||||
```mdx-code-block
|
||||
<Tabs>
|
||||
<TabItem value="html" label="login.component.html">
|
||||
```
|
||||
|
||||
```html {2} title="login.component.html" showLineNumbers
|
||||
<hanko-auth
|
||||
(success)="redirectToProfile()"
|
||||
[api]="hankoApi"
|
||||
[lang]="hankoLang">
|
||||
</hanko-auth>
|
||||
```
|
||||
|
||||
```mdx-code-block
|
||||
</TabItem>
|
||||
<TabItem value="ts" label="login.component.ts">
|
||||
```
|
||||
|
||||
```js {3,15-19} title="login.component.ts" showLineNumbers
|
||||
import { Component } from '@angular/core';
|
||||
import { environment } from '../../../environments/environment';
|
||||
import { Router } from '@angular/router';
|
||||
import '@teamhanko/hanko-elements/hanko-auth';
|
||||
|
||||
@Component({
|
||||
selector: 'app-login',
|
||||
templateUrl: './login.component.html',
|
||||
styleUrls: ['./login.component.css'],
|
||||
})
|
||||
export class LoginComponent {
|
||||
hankoApi = environment.hankoApi;
|
||||
hankoLang = environment.hankoLang;
|
||||
|
||||
constructor(private router: Router) {}
|
||||
|
||||
redirectToProfile() {
|
||||
this.router.navigate(['/profile']);
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
```mdx-code-block
|
||||
</TabItem>
|
||||
</Tabs>
|
||||
```
|
||||
|
||||
## Backend request authentication
|
||||
|
||||
If you want to authenticate requests in your own backend, please view our [backend guide](/guides/backend).
|
||||
60
docs/docs/guides/backend.mdx
Normal file
@ -0,0 +1,60 @@
|
||||
---
|
||||
sidebar_label: Backend guide
|
||||
sidebar_position: 3
|
||||
description: "Learn how to authenticate requests in your backend by verifying JWTs (JSON Web Token) using a JWK (JSON Web Key Set)."
|
||||
---
|
||||
|
||||
# Backend guide
|
||||
|
||||
After a successful login Hanko issues a cookie containing a JSON Web Token
|
||||
([JWT](https://datatracker.ietf.org/doc/html/rfc7519)). You can use this JWT to authenticate
|
||||
requests on your backend. To do so, first retrieve the JSON Web Key Set
|
||||
([JWKS](https://datatracker.ietf.org/doc/html/rfc7517))
|
||||
containing the public keys used to verify the JSON Web Token (JWT) from the Hanko API's `.well-known/jwks.json` endpoint.
|
||||
Then use the JWKS to verify the JWT using a library for the programming language of your choice.
|
||||
|
||||
The following code shows an example of a custom middleware in a Go-based backend using
|
||||
[Echo](https://echo.labstack.com/) and the [lestrrat-go/jwx](https://github.com/lestrrat-go/jwx) package:
|
||||
|
||||
```go
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
"github.com/labstack/echo/v4"
|
||||
"github.com/lestrrat-go/jwx/v2/jwk"
|
||||
"github.com/lestrrat-go/jwx/v2/jwt"
|
||||
"log"
|
||||
"net/http"
|
||||
)
|
||||
|
||||
func SessionMiddleware(hankoUrl string) echo.MiddlewareFunc {
|
||||
return func(next echo.HandlerFunc) echo.HandlerFunc {
|
||||
return func(c echo.Context) error {
|
||||
cookie, err := c.Cookie("hanko")
|
||||
if err == http.ErrNoCookie {
|
||||
return c.Redirect(http.StatusTemporaryRedirect, "/unauthorized")
|
||||
}
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
// replace "hankoApiURL" with your API URL
|
||||
set, err := jwk.Fetch(context.Background(), fmt.Sprintf("%v/.well-known/jwks.json", hankoApiURL))
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
token, err := jwt.Parse([]byte(cookie.Value), jwt.WithKeySet(set))
|
||||
if err != nil {
|
||||
return c.Redirect(http.StatusTemporaryRedirect, "/unauthorized")
|
||||
}
|
||||
|
||||
log.Printf("session for user '%s' verified successfully", token.Subject())
|
||||
|
||||
c.Set("token", cookie.Value)
|
||||
c.Set("user", token.Subject())
|
||||
|
||||
return next(c)
|
||||
}
|
||||
}
|
||||
}
|
||||
```
|
||||
105
docs/docs/guides/next.mdx
Normal file
@ -0,0 +1,105 @@
|
||||
---
|
||||
title: Next.js + Hanko
|
||||
sidebar_label: Next.js
|
||||
keywords: [next, nextjs]
|
||||
sidebar_custom_props:
|
||||
docCardIconName: nextjs-dark
|
||||
---
|
||||
|
||||
# Next.js
|
||||
|
||||
In this guide you will learn how to add authentication to your Next.js application using the Hanko custom element.
|
||||
|
||||
## Install dependencies
|
||||
|
||||
Install the `@teamhanko/hanko-elements` package:
|
||||
|
||||
```shell npm2yarn
|
||||
npm install @teamhanko/hanko-elements
|
||||
```
|
||||
|
||||
## Import & use custom element
|
||||
|
||||
Import `@teamhanko/hanko-elements/hanko-auth` in the component where you want to use the Hanko custom element.
|
||||
|
||||
```jsx title="HankoAuth.jsx" showLineNumbers
|
||||
import "@teamhanko/hanko-elements/hanko-auth";
|
||||
|
||||
export default function HankoAuth() {
|
||||
return (
|
||||
<hanko-auth
|
||||
api={process.env.NEXT_PUBLIC_HANKO_API}
|
||||
lang={process.env.NEXT_PUBLIC_HANKO_LANG}
|
||||
/>
|
||||
);
|
||||
}
|
||||
```
|
||||
|
||||
If you used this component in your application, the import would attempt to register the `<hanko-auth>` element with the
|
||||
browser's [`CustomElementRegistry`](https://developer.mozilla.org/de/docs/Web/API/CustomElementRegistry) through a
|
||||
call to `window.customElements.define()`.
|
||||
Next.js pre-renders pages on the server but the browser `window` is not available during pre-rendering, so the custom
|
||||
element registration would fail.
|
||||
|
||||
A solution for this is to use Next's [dynamic import](https://nextjs.org/docs/advanced-features/dynamic-import) feature
|
||||
to dynamically load the component on the client-side and disable server rendering for it:
|
||||
|
||||
```jsx title="index.js" showLineNumbers
|
||||
import dynamic from "next/dynamic";
|
||||
|
||||
export default function Home() {
|
||||
const HankoAuthNoSSR = dynamic(
|
||||
// replace with path to your component using the <hanko-auth> element
|
||||
() => import('../components/HankoAuth'),
|
||||
{ ssr: false },
|
||||
)
|
||||
return (
|
||||
<Suspense fallback={"Loading ..."}>
|
||||
<HankoAuthNoSSR/>
|
||||
</Suspense>
|
||||
)
|
||||
}
|
||||
```
|
||||
|
||||
## Defining login callbacks
|
||||
|
||||
The `<hanko-auth>` element dispatches a custom `success` event on successful login. React to this
|
||||
event in order to, for example, redirect your users to protected pages in your application.
|
||||
|
||||
To do so, create a [`ref`](https://reactjs.org/docs/hooks-reference.html#useref) to obtain access to the `<hanko-auth>`
|
||||
DOM element and apply an event listener with an appropriate redirect callback:
|
||||
|
||||
```jsx {1-2,6-18,22} title="HankoAuth.jsx" showLineNumbers
|
||||
import React, { useEffect, useRef } from "react";
|
||||
import { useRouter } from "next/router";
|
||||
import "@teamhanko/hanko-elements/hanko-auth";
|
||||
|
||||
export default function HankoAuth() {
|
||||
const router = useRouter();
|
||||
const ref = useRef(null);
|
||||
|
||||
const redirectToProfile = () => {
|
||||
router.replace("/profile");
|
||||
}
|
||||
|
||||
useEffect(() => {
|
||||
const { current } = ref;
|
||||
|
||||
current?.addEventListener("success", redirectToProfile);
|
||||
return () => current?.removeEventListener("success", redirectToProfile);
|
||||
}, []);
|
||||
|
||||
return (
|
||||
<hanko-auth
|
||||
ref={ref}
|
||||
api={process.env.NEXT_PUBLIC_HANKO_API}
|
||||
lang={process.env.NEXT_PUBLIC_HANKO_LANG}
|
||||
/>
|
||||
);
|
||||
}
|
||||
```
|
||||
|
||||
## Backend request authentication
|
||||
|
||||
If you want to authenticate requests in your own backend, please view our [backend guide](/guides/backend).
|
||||
|
||||
82
docs/docs/guides/react.mdx
Normal file
@ -0,0 +1,82 @@
|
||||
---
|
||||
title: React + Hanko
|
||||
sidebar_label: React
|
||||
keywords: [react]
|
||||
sidebar_custom_props:
|
||||
docCardIconName: react
|
||||
---
|
||||
|
||||
# React
|
||||
|
||||
In this guide you will learn how to add authentication to your React application using the Hanko custom element.
|
||||
|
||||
## Install dependencies
|
||||
Install the `@teamhanko/hanko-elements` package:
|
||||
|
||||
```shell npm2yarn
|
||||
npm install @teamhanko/hanko-elements
|
||||
```
|
||||
|
||||
## Import & use custom element
|
||||
|
||||
Import `@teamhanko/hanko-elements/hanko-auth` in the component where you want to use the Hanko custom element.
|
||||
Doing so registers the `<hanko-auth>` element with the browser's
|
||||
[`CustomElementRegistry`](https://developer.mozilla.org/de/docs/Web/API/CustomElementRegistry). Then use the element
|
||||
in your JSX:
|
||||
|
||||
```jsx {1,4-7} title="HankoAuth.jsx" showLineNumbers
|
||||
import "@teamhanko/hanko-elements/hanko-auth";
|
||||
|
||||
function HankoAuth() {
|
||||
return <hanko-auth
|
||||
api={process.env.NEXT_PUBLIC_HANKO_API}
|
||||
lang={process.env.NEXT_PUBLIC_HANKO_LANG}
|
||||
/>;
|
||||
}
|
||||
|
||||
export default HankoAuth;
|
||||
```
|
||||
|
||||
## Defining login callbacks
|
||||
|
||||
The `<hanko-auth>` element dispatches a custom `success` event on successful login. React to this
|
||||
event in order to, for example, redirect your users to protected pages in your application.
|
||||
|
||||
To do so, create a [`ref`](https://reactjs.org/docs/hooks-reference.html#useref) to obtain access to the `<hanko-auth>`
|
||||
DOM element and apply an event listener with an appropriate redirect callback:
|
||||
|
||||
```jsx {1-2,6-18,22} title="HankoAuth.jsx" showLineNumbers
|
||||
import React, { useEffect, useRef } from "react";
|
||||
import { useNavigate } from "react-router-dom";
|
||||
import "@teamhanko/hanko-elements/hanko-auth";
|
||||
|
||||
function HankoAuth() {
|
||||
const ref = useRef(null);
|
||||
const navigate = useNavigate();
|
||||
|
||||
const redirectToProfile = () => {
|
||||
navigate("/profile", { replace: true });
|
||||
}
|
||||
|
||||
useEffect(() => {
|
||||
const { current } = ref;
|
||||
|
||||
current?.addEventListener("success", redirectToProfile);
|
||||
return () => current?.removeEventListener("success", redirectToProfile);
|
||||
}, []);
|
||||
|
||||
return (
|
||||
<hanko-auth
|
||||
ref={ref}
|
||||
api={process.env.REACT_APP_HANKO_API}
|
||||
lang={process.env.REACT_APP_HANKO_LANG}
|
||||
/>
|
||||
);
|
||||
}
|
||||
|
||||
export default HankoAuth;
|
||||
```
|
||||
|
||||
## Backend request authentication
|
||||
|
||||
If you want to authenticate requests in your own backend, please view our [backend guide](/guides/backend).
|
||||
127
docs/docs/guides/vue.mdx
Normal file
@ -0,0 +1,127 @@
|
||||
---
|
||||
title: Vue + Hanko
|
||||
sidebar_label: Vue
|
||||
keywords: [vue]
|
||||
sidebar_custom_props:
|
||||
docCardIconName: vue
|
||||
---
|
||||
|
||||
import Tabs from '@theme/Tabs';
|
||||
import TabItem from '@theme/TabItem';
|
||||
|
||||
# Vue
|
||||
|
||||
In this guide you will learn how to add authentication to your Vue application using the Hanko custom element.
|
||||
|
||||
## Install dependencies
|
||||
|
||||
Install the `@teamhanko/hanko-elements` package:
|
||||
|
||||
```shell npm2yarn
|
||||
npm install @teamhanko/hanko-elements
|
||||
```
|
||||
|
||||
## Register custom element with Vue
|
||||
|
||||
Vue needs to know which elements to treat as custom elements, otherwise it will issue a warning regarding component
|
||||
resolution. To do so, provide a predicate function that determines which elements are to be considered custom elements
|
||||
to `compilerOptions.isCustomElement` in your configuration:
|
||||
|
||||
```mdx-code-block
|
||||
<Tabs>
|
||||
<TabItem value="vite" label="Vite Config">
|
||||
```
|
||||
|
||||
```js {7-9} title="vite.config.js" showLineNumbers
|
||||
import vue from '@vitejs/plugin-vue'
|
||||
|
||||
export default {
|
||||
plugins: [
|
||||
vue({
|
||||
template: {
|
||||
compilerOptions: {
|
||||
isCustomElement: (tag) => tag === "hanko-auth"
|
||||
}
|
||||
}
|
||||
})
|
||||
]
|
||||
}
|
||||
```
|
||||
|
||||
```mdx-code-block
|
||||
</TabItem>
|
||||
<TabItem value="cli" label="Vue CLI Config">
|
||||
```
|
||||
|
||||
```js {8-10} title="vue.config.js" showLineNumbers
|
||||
module.exports = {
|
||||
chainWebpack: config => {
|
||||
config.module
|
||||
.rule('vue')
|
||||
.use('vue-loader')
|
||||
.tap(options => ({
|
||||
...options,
|
||||
compilerOptions: {
|
||||
isCustomElement: (tag) => tag === "hanko-auth"
|
||||
}
|
||||
}))
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
```mdx-code-block
|
||||
</TabItem>
|
||||
</Tabs>
|
||||
```
|
||||
|
||||
## Import & use custom element
|
||||
|
||||
Import `@teamhanko/hanko-elements/hanko-auth` in the component where you want to use the Hanko custom element.
|
||||
Doing so registers the `<hanko-auth>` element with the browser's
|
||||
[`CustomElementRegistry`](https://developer.mozilla.org/de/docs/Web/API/CustomElementRegistry). Then use the
|
||||
element in your component template:
|
||||
|
||||
```js title="HankoAuth.vue" showLineNumbers
|
||||
<script setup>
|
||||
import "@teamhanko/hanko-elements/hanko-auth";
|
||||
|
||||
const api = import.meta.env.VITE_HANKO_API;
|
||||
const lang = import.meta.env.VITE_HANKO_LANG;
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<hanko-auth :api="api" :lang="lang" />
|
||||
</template>
|
||||
```
|
||||
|
||||
## Defining login callbacks
|
||||
|
||||
The `<hanko-auth>` element dispatches a custom `success` event on successful login. React to this
|
||||
event in order to, for example, redirect your users to protected pages in your application.
|
||||
|
||||
To do so, you can use Vue's [`v-on`](https://vuejs.org/guide/essentials/event-handling.html#listening-to-events)
|
||||
directive (shorthand: `@`) and supply a callback directly on the `<hanko-auth>` element:
|
||||
|
||||
```js {2,8-12,16} title="HankoAuth.vue" showLineNumbers
|
||||
<script setup>
|
||||
import { useRouter } from "vue-router";
|
||||
import "@teamhanko/hanko-elements/hanko-auth";
|
||||
|
||||
const api = import.meta.env.VITE_HANKO_API;
|
||||
const lang = import.meta.env.VITE_HANKO_LANG;
|
||||
|
||||
const router = useRouter();
|
||||
|
||||
const redirectToProfile = () => {
|
||||
router.push({ path: "/profile" });
|
||||
};
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<hanko-auth @success="redirectToProfile" :api="api" :lang="lang" />
|
||||
</template>
|
||||
```
|
||||
|
||||
## Backend request authentication
|
||||
|
||||
If you want to authenticate requests in your own backend, please view our [backend guide](/guides/backend).
|
||||
21
docs/docs/intro.md
Normal file
@ -0,0 +1,21 @@
|
||||
---
|
||||
sidebar_position: 1
|
||||
slug: /
|
||||
title: Introduction
|
||||
---
|
||||
# :wave: Welcome to Hanko Docs
|
||||
Hanko is a lightweight, open source user authentication solution that takes you on the journey beyond passwords. For better security, increased conversion rates, and happier users.
|
||||
|
||||
## Get started with Hanko
|
||||
To get started with Hanko, visit the [Hanko project](https://github.com/teamhanko/hanko) on GitHub and follow the instructions to get Hanko up and running locally.
|
||||
|
||||
## Integrate Hanko
|
||||
To integrate Hanko into your project, we are providing [guides](/guides/frontend) for popular frontend frameworks.
|
||||
|
||||
## Give feedback
|
||||
We'd love to hear your thoughts about Hanko, especially if you encounter any problems. Please do not hesitate to reach out. You can find us on
|
||||
- [Hanko Community Slack](https://www.hanko.io/community)
|
||||
- [Twitter](https://twitter.com/hanko_io)
|
||||
|
||||
## Contribute
|
||||
Contributions to the Hanko project are appreciated. For more complex topics, we encourage you to talk to us first to avoid misunderstandings. We're actively working on Hanko and may have already started implementing certain features.
|
||||
162
docs/docusaurus.config.js
Normal file
@ -0,0 +1,162 @@
|
||||
// @ts-check
|
||||
// Note: type annotations allow type checking and IDEs autocompletion
|
||||
|
||||
const lightCodeTheme = require('prism-react-renderer/themes/github');
|
||||
const darkCodeTheme = require('prism-react-renderer/themes/dracula');
|
||||
|
||||
/** @type {import('@docusaurus/types').Config} */
|
||||
const config = {
|
||||
title: 'Hanko Documentation',
|
||||
tagline: 'Hanko Documentation',
|
||||
url: 'https://docs.hanko.io',
|
||||
baseUrl: '/',
|
||||
onBrokenLinks: 'throw',
|
||||
onBrokenMarkdownLinks: 'warn',
|
||||
favicon: 'img/favicon.ico',
|
||||
|
||||
// GitHub pages deployment config.
|
||||
// If you aren't using GitHub pages, you don't need these.
|
||||
organizationName: 'teamhanko', // Usually your GitHub org/user name.
|
||||
projectName: 'docs', // Usually your repo name.
|
||||
trailingSlash: false,
|
||||
|
||||
// Even if you don't use internalization, you can use this field to set useful
|
||||
// metadata like html lang. For example, if your site is Chinese, you may want
|
||||
// to replace "en" with "zh-Hans".
|
||||
i18n: {
|
||||
defaultLocale: 'en',
|
||||
locales: ['en'],
|
||||
},
|
||||
|
||||
presets: [
|
||||
[
|
||||
'redocusaurus',
|
||||
{
|
||||
// Plugin Options for loading OpenAPI files
|
||||
specs: [
|
||||
{
|
||||
spec: 'static/spec/api.yaml',
|
||||
route: '/api',
|
||||
},
|
||||
],
|
||||
// Theme Options for modifying how redoc renders them
|
||||
theme: {
|
||||
primaryColor: '#ff2e4c',
|
||||
primaryColorDark: '#aedfff',
|
||||
options : {
|
||||
nativeScrollbars: true,
|
||||
scrollYOffset: 60,
|
||||
disableSearch: true,
|
||||
noAutoAuth: true,
|
||||
expandResponses: '200',
|
||||
jsonSampleExpandLevel: 3,
|
||||
pathInMiddlePanel: false,
|
||||
requiredPropsFirst: true,
|
||||
hideDownloadButton: true
|
||||
},
|
||||
// Change with your site colors
|
||||
theme: {
|
||||
typography: {
|
||||
fontSize: '16px',
|
||||
fontWeightRegular: '500',
|
||||
code: {
|
||||
fontSize: '13px',
|
||||
fontFamily: 'Courier, monospace',
|
||||
}
|
||||
},
|
||||
sidebar: {
|
||||
arrow: {
|
||||
size: '1.7em',
|
||||
color: '#7f7f7f'
|
||||
},
|
||||
width: '300px',
|
||||
},
|
||||
}
|
||||
},
|
||||
},
|
||||
],
|
||||
[
|
||||
'classic',
|
||||
/** @type {import('@docusaurus/preset-classic').Options} */
|
||||
({
|
||||
docs: {
|
||||
routeBasePath: '/', // Serve the docs at the site's root
|
||||
sidebarPath: require.resolve('./sidebars.js'),
|
||||
remarkPlugins: [require('@docusaurus/remark-plugin-npm2yarn'), {sync: true}],
|
||||
},
|
||||
blog: false,
|
||||
theme: {
|
||||
customCss: [require.resolve('./src/css/custom.css'), require.resolve('./src/css/redoc.css')]
|
||||
},
|
||||
}),
|
||||
],
|
||||
],
|
||||
|
||||
themeConfig:
|
||||
/** @type {import('@docusaurus/preset-classic').ThemeConfig} */
|
||||
({
|
||||
docs: {
|
||||
sidebar: {
|
||||
hideable: true
|
||||
}
|
||||
},
|
||||
image: 'img/thumbnail.jpg',
|
||||
announcementBar: {
|
||||
id: 'support_us',
|
||||
content:
|
||||
'⚠️ This documentation is currently a work in progress, stay tuned for more content! ⚠️',
|
||||
backgroundColor: '#83ceff',
|
||||
textColor: '#091E42',
|
||||
isCloseable: true,
|
||||
},
|
||||
colorMode: {
|
||||
defaultMode: 'dark',
|
||||
disableSwitch: true,
|
||||
},
|
||||
navbar: {
|
||||
logo: {
|
||||
alt: 'Hanko Logo',
|
||||
src: 'img/logo.svg',
|
||||
href: '/',
|
||||
},
|
||||
items: [
|
||||
{
|
||||
to: '/',
|
||||
label: 'Docs',
|
||||
position: 'left',
|
||||
activeBaseRegex: '^((?!\/api).)*$'
|
||||
},
|
||||
{
|
||||
to: '/api',
|
||||
label: 'API',
|
||||
position: 'left',
|
||||
},
|
||||
{
|
||||
type: 'dropdown',
|
||||
label: 'SDK',
|
||||
position: 'left',
|
||||
items: [
|
||||
{
|
||||
to: 'jsdoc/@teamhanko/hanko-frontend-sdk/0.0.1-alpha/index.html',
|
||||
label: 'Frontend 0.0.1-alpha',
|
||||
target: '_blank'
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
href: 'https://github.com/teamhanko/hanko',
|
||||
title: "Visit us on GitHub!",
|
||||
position: 'right',
|
||||
className: 'header-github-link',
|
||||
'aria-label': 'Visit us on GitHub!',
|
||||
},
|
||||
],
|
||||
},
|
||||
prism: {
|
||||
theme: lightCodeTheme,
|
||||
darkTheme: darkCodeTheme,
|
||||
},
|
||||
}),
|
||||
};
|
||||
|
||||
module.exports = config;
|
||||
@ -1,29 +0,0 @@
|
||||
<html>
|
||||
<head>
|
||||
<!-- Load the latest Swagger UI code and style from npm using unpkg.com -->
|
||||
<script src="https://unpkg.com/swagger-ui-dist@3/swagger-ui-bundle.js"></script>
|
||||
<link rel="stylesheet" type="text/css" href="https://unpkg.com/swagger-ui-dist@3/swagger-ui.css"/>
|
||||
<title>Hanko</title>
|
||||
</head>
|
||||
<body>
|
||||
<div id="swagger-ui"></div> <!-- Div to hold the UI component -->
|
||||
<script>
|
||||
window.onload = function () {
|
||||
// Begin Swagger UI call region
|
||||
const ui = SwaggerUIBundle({
|
||||
url: "spec/api.yaml",
|
||||
dom_id: '#swagger-ui',
|
||||
deepLinking: true,
|
||||
presets: [
|
||||
SwaggerUIBundle.presets.apis,
|
||||
SwaggerUIBundle.SwaggerUIStandalonePreset
|
||||
],
|
||||
plugins: [
|
||||
SwaggerUIBundle.plugins.DownloadUrl
|
||||
],
|
||||
})
|
||||
window.ui = ui
|
||||
}
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
||||
22945
docs/package-lock.json
generated
Normal file
48
docs/package.json
Normal file
@ -0,0 +1,48 @@
|
||||
{
|
||||
"name": "@teamhanko/docs",
|
||||
"version": "0.2.0",
|
||||
"private": true,
|
||||
"scripts": {
|
||||
"docusaurus": "docusaurus",
|
||||
"start": "docusaurus start --port 3001",
|
||||
"build": "docusaurus build",
|
||||
"swizzle": "docusaurus swizzle",
|
||||
"deploy": "docusaurus deploy",
|
||||
"clear": "docusaurus clear",
|
||||
"serve": "docusaurus serve",
|
||||
"write-translations": "docusaurus write-translations",
|
||||
"write-heading-ids": "docusaurus write-heading-ids",
|
||||
"typecheck": "tsc"
|
||||
},
|
||||
"dependencies": {
|
||||
"@docusaurus/core": "^2.0.1",
|
||||
"@docusaurus/preset-classic": "^2.0.1",
|
||||
"@docusaurus/remark-plugin-npm2yarn": "^2.0.1",
|
||||
"@mdx-js/react": "^1.6.22",
|
||||
"clsx": "^1.2.1",
|
||||
"prism-react-renderer": "^1.3.5",
|
||||
"react": "^17.0.2",
|
||||
"react-dom": "^17.0.2",
|
||||
"redocusaurus": "^1.3.0"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@docusaurus/module-type-aliases": "^2.0.1",
|
||||
"@tsconfig/docusaurus": "^1.0.5",
|
||||
"typescript": "^4.7.4"
|
||||
},
|
||||
"browserslist": {
|
||||
"production": [
|
||||
">0.5%",
|
||||
"not dead",
|
||||
"not op_mini all"
|
||||
],
|
||||
"development": [
|
||||
"last 1 chrome version",
|
||||
"last 1 firefox version",
|
||||
"last 1 safari version"
|
||||
]
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=16.14"
|
||||
}
|
||||
}
|
||||
38
docs/sidebars.js
Normal file
@ -0,0 +1,38 @@
|
||||
/**
|
||||
* Creating a sidebar enables you to:
|
||||
- create an ordered group of docs
|
||||
- render a sidebar for each doc of that group
|
||||
- provide next/previous navigation
|
||||
|
||||
The sidebars can be generated from the filesystem, or explicitly defined here.
|
||||
|
||||
Create as many sidebars as you want.
|
||||
*/
|
||||
|
||||
// @ts-check
|
||||
|
||||
/** @type {import('@docusaurus/plugin-content-docs').SidebarsConfig} */
|
||||
const sidebars = {
|
||||
// By default, Docusaurus generates a sidebar from the docs folder structure
|
||||
// tutorialSidebar: [{type: 'autogenerated', dirName: '.'}],
|
||||
|
||||
// But you can create a sidebar manually
|
||||
docs: [
|
||||
'intro',
|
||||
{
|
||||
type: 'category',
|
||||
label: 'Frontend guides',
|
||||
link: {
|
||||
type: 'generated-index',
|
||||
title: 'Frontend guides',
|
||||
description: 'Set up authentication for your app in minutes by learning how to integrate Hanko with your preferred frontend framework!',
|
||||
slug: '/guides/frontend',
|
||||
keywords: ['guides']
|
||||
},
|
||||
items: ['guides/angular', "guides/react", "guides/next", "guides/vue"]
|
||||
},
|
||||
'guides/backend'
|
||||
],
|
||||
};
|
||||
|
||||
module.exports = sidebars;
|
||||
52
docs/src/css/custom.css
Normal file
@ -0,0 +1,52 @@
|
||||
/**
|
||||
* Any CSS included here will be global. The classic template
|
||||
* bundles Infima by default. Infima is a CSS framework designed to
|
||||
* work well for content-centric websites.
|
||||
*/
|
||||
|
||||
/* You can override the default Infima variables here. */
|
||||
:root {
|
||||
--ifm-color-primary: #ff2e4c;
|
||||
--ifm-color-primary-dark: #ff1032;
|
||||
--ifm-color-primary-darker: #ff0125;
|
||||
--ifm-color-primary-darkest: #d3001e;
|
||||
--ifm-color-primary-light: #ff4c66;
|
||||
--ifm-color-primary-lighter: #ff5b73;
|
||||
--ifm-color-primary-lightest: #ff8899;
|
||||
--ifm-code-font-size: 95%;
|
||||
--docusaurus-highlighted-code-line-bg: rgba(0, 0, 0, 0.1);
|
||||
}
|
||||
|
||||
/* For readability concerns, you should choose a lighter palette in dark mode. */
|
||||
[data-theme='dark'] {
|
||||
--ifm-color-primary: #aedfff;
|
||||
--ifm-color-primary-dark: #83ceff;
|
||||
--ifm-color-primary-darker: #6ec6ff;
|
||||
--ifm-color-primary-darkest: #2dacff;
|
||||
--ifm-color-primary-light: #d9f0ff;
|
||||
--ifm-color-primary-lighter: #eef8ff;
|
||||
--ifm-color-primary-lightest: #ffffff;
|
||||
--docusaurus-highlighted-code-line-bg: rgba(0, 0, 0, 0.3);
|
||||
}
|
||||
|
||||
html[data-theme='dark'] {
|
||||
--ifm-background-color: #0b0d0e;
|
||||
}
|
||||
|
||||
.header-github-link:hover {
|
||||
opacity: 0.6;
|
||||
}
|
||||
|
||||
.header-github-link::before {
|
||||
content: '';
|
||||
width: 24px;
|
||||
height: 24px;
|
||||
display: flex;
|
||||
background: url("data:image/svg+xml,%3Csvg viewBox='0 0 24 24' xmlns='http://www.w3.org/2000/svg'%3E%3Cpath d='M12 .297c-6.63 0-12 5.373-12 12 0 5.303 3.438 9.8 8.205 11.385.6.113.82-.258.82-.577 0-.285-.01-1.04-.015-2.04-3.338.724-4.042-1.61-4.042-1.61C4.422 18.07 3.633 17.7 3.633 17.7c-1.087-.744.084-.729.084-.729 1.205.084 1.838 1.236 1.838 1.236 1.07 1.835 2.809 1.305 3.495.998.108-.776.417-1.305.76-1.605-2.665-.3-5.466-1.332-5.466-5.93 0-1.31.465-2.38 1.235-3.22-.135-.303-.54-1.523.105-3.176 0 0 1.005-.322 3.3 1.23.96-.267 1.98-.399 3-.405 1.02.006 2.04.138 3 .405 2.28-1.552 3.285-1.23 3.285-1.23.645 1.653.24 2.873.12 3.176.765.84 1.23 1.91 1.23 3.22 0 4.61-2.805 5.625-5.475 5.92.42.36.81 1.096.81 2.22 0 1.606-.015 2.896-.015 3.286 0 .315.21.69.825.57C20.565 22.092 24 17.592 24 12.297c0-6.627-5.373-12-12-12'/%3E%3C/svg%3E")
|
||||
no-repeat;
|
||||
}
|
||||
|
||||
[data-theme='dark'] .header-github-link::before {
|
||||
background: url("data:image/svg+xml,%3Csvg viewBox='0 0 24 24' xmlns='http://www.w3.org/2000/svg'%3E%3Cpath fill='white' d='M12 .297c-6.63 0-12 5.373-12 12 0 5.303 3.438 9.8 8.205 11.385.6.113.82-.258.82-.577 0-.285-.01-1.04-.015-2.04-3.338.724-4.042-1.61-4.042-1.61C4.422 18.07 3.633 17.7 3.633 17.7c-1.087-.744.084-.729.084-.729 1.205.084 1.838 1.236 1.838 1.236 1.07 1.835 2.809 1.305 3.495.998.108-.776.417-1.305.76-1.605-2.665-.3-5.466-1.332-5.466-5.93 0-1.31.465-2.38 1.235-3.22-.135-.303-.54-1.523.105-3.176 0 0 1.005-.322 3.3 1.23.96-.267 1.98-.399 3-.405 1.02.006 2.04.138 3 .405 2.28-1.552 3.285-1.23 3.285-1.23.645 1.653.24 2.873.12 3.176.765.84 1.23 1.91 1.23 3.22 0 4.61-2.805 5.625-5.475 5.92.42.36.81 1.096.81 2.22 0 1.606-.015 2.896-.015 3.286 0 .315.21.69.825.57C20.565 22.092 24 17.592 24 12.297c0-6.627-5.373-12-12-12'/%3E%3C/svg%3E")
|
||||
no-repeat;
|
||||
}
|
||||
218
docs/src/css/redoc.css
Normal file
@ -0,0 +1,218 @@
|
||||
/* Redoc sidebar menu styles */
|
||||
.redoc-wrap > .menu-content ul > li {
|
||||
margin: 0.25rem 0;
|
||||
}
|
||||
|
||||
.redoc-wrap > .menu-content {
|
||||
padding: 8px;
|
||||
}
|
||||
|
||||
.redoc-wrap > .menu-content ul > li > label {
|
||||
border-radius: 0.25rem;
|
||||
color: var(--ifm-menu-color);
|
||||
cursor: pointer;
|
||||
display: flex;
|
||||
line-height: 20px;
|
||||
justify-content: space-between;
|
||||
padding: var(--ifm-menu-link-padding-vertical) var(--ifm-menu-link-padding-horizontal);
|
||||
}
|
||||
|
||||
.main-wrapper .redoc-wrap .menu-content {
|
||||
border-right: 1px solid var(--ifm-toc-border-color);
|
||||
}
|
||||
|
||||
html[data-theme='dark'] .main-wrapper .redoc-wrap .menu-content {
|
||||
background-color: #0b0d0e;
|
||||
}
|
||||
|
||||
.redoc-wrap .menu-content label[role=menuitem] {
|
||||
font-size: 1rem;
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
html[data-theme='dark'] .redoc-wrap .menu-content label[role=menuitem] {
|
||||
background-color: #0b0d0e;
|
||||
}
|
||||
|
||||
html[data-theme='dark'] .redoc-wrap .menu-content label[role=menuitem] {
|
||||
font-size: 1rem;
|
||||
align-items: center;
|
||||
background-color: #0b0d0e;
|
||||
}
|
||||
|
||||
.redoc-wrap .menu-content label[role=menuitem].active {
|
||||
background-color: var(--ifm-menu-color-background-hover) !important;
|
||||
}
|
||||
|
||||
.redoc-wrap .menu-content label[role=menuitem]:hover {
|
||||
font-size: 1rem;
|
||||
align-items: center;
|
||||
background-color: var(--ifm-menu-color-background-hover);
|
||||
}
|
||||
|
||||
html[data-theme='dark'] .redoc-wrap .menu-content label[role=menuitem]:hover {
|
||||
font-size: 1rem;
|
||||
align-items: center;
|
||||
background-color: var(--ifm-menu-color-background-hover);
|
||||
}
|
||||
|
||||
.redoc-wrap .menu-content .operation-type {
|
||||
margin-top: 0;
|
||||
}
|
||||
|
||||
.redoc-wrap .menu-content ul[role='navigation'] > li:first-child {
|
||||
margin-top: 0;
|
||||
}
|
||||
|
||||
/* Redoc main content table styles */
|
||||
.redoc-wrap > .api-content table {
|
||||
display: table;
|
||||
font-size: 13px;
|
||||
}
|
||||
|
||||
.redoc-wrap .api-content table tr {
|
||||
border-top: none;
|
||||
}
|
||||
|
||||
.redoc-wrap .api-content table td[kind=field] {
|
||||
border-top: none;
|
||||
border-bottom: none;
|
||||
border-right: none;
|
||||
border-left-color: var(--ifm-color-primary);
|
||||
}
|
||||
|
||||
.redoc-wrap .api-content table td[kind=field] span:first-child::before,
|
||||
.redoc-wrap .api-content table td[kind=field] span:first-child::after {
|
||||
background-color: var(--ifm-color-primary)
|
||||
}
|
||||
|
||||
.redoc-wrap .api-content table td[kind=field] + td {
|
||||
border-top: none;
|
||||
border-left: none;
|
||||
border-right: none;
|
||||
}
|
||||
|
||||
@media screen and (max-width: 50rem) {
|
||||
.redoc-wrap .api-content table td[kind=field] + td {
|
||||
border-left: 1px solid var(--ifm-color-primary);
|
||||
}
|
||||
html[data-theme='dark'] .redoc-wrap .api-content table td[kind=field] + td {
|
||||
border-left: 1px solid var(--ifm-color-primary);
|
||||
}
|
||||
}
|
||||
|
||||
@media screen and (max-width: 50rem) {
|
||||
.redoc-wrap .api-content table tr.last td~td {
|
||||
border-left: none;
|
||||
}
|
||||
html[data-theme='dark'] .redoc-wrap .api-content table tr.last td~td {
|
||||
border-left: none;
|
||||
}
|
||||
}
|
||||
|
||||
.redoc-wrap .api-content table tr.expanded + tr > td {
|
||||
border-top: none;
|
||||
border-bottom: none;
|
||||
border-right: none;
|
||||
}
|
||||
|
||||
.redoc-wrap .api-content table table tr:nth-child(n) {
|
||||
background-color: inherit;
|
||||
}
|
||||
|
||||
.redoc-wrap .api-content tr:first-of-type > td[kind="field"] {
|
||||
background-image: linear-gradient( to bottom, transparent 0%, transparent 22px, var(--ifm-color-primary) 22px, var(--ifm-color-primary) 100% );
|
||||
border-left-width: 0;
|
||||
background-position: top left;
|
||||
background-repeat: no-repeat;
|
||||
background-size: 1px 100%;
|
||||
}
|
||||
|
||||
.redoc-wrap .api-content tr.last > td[kind="field"] {
|
||||
background-image: linear-gradient( to bottom, var(--ifm-color-primary) 0%, var(--ifm-color-primary) 22px, transparent 22px, transparent 100% );
|
||||
}
|
||||
|
||||
.redoc-wrap .api-content tr.last:first-child > td[kind="field"] {
|
||||
background: none;
|
||||
border-left-color: transparent;
|
||||
}
|
||||
|
||||
.redoc-wrap .api-content table tbody tr table tbody tr > td[colspan] {
|
||||
border-left-color: var(--ifm-color-primary) !important;
|
||||
}
|
||||
|
||||
html[data-theme='dark'] .redoc-wrap .api-content tr.last:first-child > td[kind="field"] {
|
||||
background: none;
|
||||
border-left-color: transparent;
|
||||
}
|
||||
|
||||
html[data-theme='dark'] .redoc-wrap .api-content tr.last > td[kind="field"] {
|
||||
background-image: linear-gradient( to bottom, var(--ifm-color-primary) 0%, var(--ifm-color-primary) 22px, transparent 22px, transparent 100% );
|
||||
}
|
||||
|
||||
html[data-theme='dark'] .redoc-wrap .api-content table caption {
|
||||
color: var(--ifm-color-white);
|
||||
}
|
||||
|
||||
html[data-theme='dark'] .redoc-wrap .api-content table tbody tr table {
|
||||
background: none !important;
|
||||
}
|
||||
|
||||
html[data-theme='dark'] .redoc-wrap .api-content table tbody tr table tbody tr > td[colspan] {
|
||||
border-left-color: var(--ifm-color-primary) !important;
|
||||
}
|
||||
|
||||
html[data-theme='dark'] .redoc-wrap .api-content table tbody tr table tbody tr > td[colspan] > div {
|
||||
background: none !important;
|
||||
}
|
||||
|
||||
/* Redoc main content misc styles */
|
||||
|
||||
.redoc-wrap a:hover {
|
||||
color: var(--ifm-color-primary) !important;
|
||||
text-decoration: underline !important;
|
||||
}
|
||||
|
||||
.redoc-wrap .api-content h3 {
|
||||
display: block;
|
||||
font-size: 1.17em;
|
||||
margin-block-start: 1em;
|
||||
margin-block-end: 1em;
|
||||
margin-inline-start: 0;
|
||||
margin-inline-end: 0;
|
||||
font-weight: bold;
|
||||
}
|
||||
|
||||
html[data-theme='dark'] .redoc-wrap .api-content h5 ~ svg {
|
||||
fill: var(--ifm-color-white);
|
||||
}
|
||||
|
||||
.redoc-wrap .api-content h3 ~ div button:not([aria-label="expand properties"]) {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
.redoc-wrap .api-content h3 ~ div button:not([aria-label="expand properties"]) span {
|
||||
padding-left: .5em;
|
||||
}
|
||||
|
||||
.react-tabs__tab-panel--selected button {
|
||||
display: inline-block !important;
|
||||
}
|
||||
|
||||
/* Code styles */
|
||||
.redoc-json code {
|
||||
color: #ffffff;
|
||||
background-color: transparent;
|
||||
padding: 0;
|
||||
}
|
||||
|
||||
.redoc-wrap .api-content code {
|
||||
color: var(--ifm-color-primary);
|
||||
}
|
||||
|
||||
.api-content pre {
|
||||
background-color: #272C30;
|
||||
}
|
||||
|
||||
|
||||
138
docs/src/theme/DocCard/index.tsx
Normal file
@ -0,0 +1,138 @@
|
||||
import React, {type ReactNode} from 'react';
|
||||
import clsx from 'clsx';
|
||||
import Link from '@docusaurus/Link';
|
||||
import {
|
||||
findFirstCategoryLink,
|
||||
useDocById,
|
||||
} from '@docusaurus/theme-common/internal';
|
||||
import isInternalUrl from '@docusaurus/isInternalUrl';
|
||||
import {translate} from '@docusaurus/Translate';
|
||||
import useBaseUrl from '@docusaurus/useBaseUrl';
|
||||
import type {Props} from '@theme/DocCard';
|
||||
|
||||
import styles from './styles.module.css';
|
||||
import type {
|
||||
PropSidebarItemCategory,
|
||||
PropSidebarItemLink,
|
||||
} from '@docusaurus/plugin-content-docs';
|
||||
|
||||
function CardContainer({
|
||||
href,
|
||||
children,
|
||||
}: {
|
||||
href: string;
|
||||
children: ReactNode;
|
||||
}): JSX.Element {
|
||||
return (
|
||||
<Link
|
||||
href={href}
|
||||
className={clsx('card padding--lg', styles.cardContainer)}>
|
||||
{children}
|
||||
</Link>
|
||||
);
|
||||
}
|
||||
|
||||
function CardLayout({
|
||||
href,
|
||||
icon,
|
||||
title,
|
||||
description,
|
||||
showDescription
|
||||
}: {
|
||||
href: string;
|
||||
icon: ReactNode;
|
||||
title: string;
|
||||
description?: string;
|
||||
showDescription?: boolean;
|
||||
}): JSX.Element {
|
||||
return (
|
||||
<CardContainer href={href}>
|
||||
<h2 className={clsx('text--truncate', styles.cardTitle)} title={title}>
|
||||
{icon} {title}
|
||||
</h2>
|
||||
{description && showDescription && (
|
||||
<p
|
||||
className={clsx('text--truncate', styles.cardDescription)}
|
||||
title={description}>
|
||||
{description}
|
||||
</p>
|
||||
)}
|
||||
</CardContainer>
|
||||
);
|
||||
}
|
||||
|
||||
function CardCategory({
|
||||
item,
|
||||
}: {
|
||||
item: PropSidebarItemCategory;
|
||||
}): JSX.Element | null {
|
||||
const href = findFirstCategoryLink(item);
|
||||
|
||||
// Unexpected: categories that don't have a link have been filtered upfront
|
||||
if (!href) {
|
||||
return null;
|
||||
}
|
||||
|
||||
const icon = <DocCardIcon item={item}/>
|
||||
|
||||
return (
|
||||
<CardLayout
|
||||
href={href}
|
||||
icon={icon}
|
||||
title={item.label}
|
||||
description={translate(
|
||||
{
|
||||
message: '{count} items',
|
||||
id: 'theme.docs.DocCard.categoryDescription',
|
||||
description:
|
||||
'The default description for a category card in the generated index about how many items this category includes',
|
||||
},
|
||||
{count: item.items.length},
|
||||
)}
|
||||
showDescription={!!item.customProps.docCardShowDescription}
|
||||
/>
|
||||
);
|
||||
}
|
||||
|
||||
function CardLink({item}: {item: PropSidebarItemLink}): JSX.Element {
|
||||
const icon = <DocCardIcon item={item}/>
|
||||
|
||||
const doc = useDocById(item.docId ?? undefined);
|
||||
return (
|
||||
<CardLayout
|
||||
href={item.href}
|
||||
icon={icon}
|
||||
title={item.label}
|
||||
description={doc?.description}
|
||||
showDescription={!!item.customProps.docCardShowDescription}
|
||||
/>
|
||||
);
|
||||
}
|
||||
|
||||
export default function DocCard({item}: Props): JSX.Element {
|
||||
switch (item.type) {
|
||||
case 'link':
|
||||
return <CardLink item={item} />;
|
||||
case 'category':
|
||||
return <CardCategory item={item} />;
|
||||
default:
|
||||
throw new Error(`unknown item type ${JSON.stringify(item)}`);
|
||||
}
|
||||
}
|
||||
|
||||
function DocCardIcon({ item }: {item: PropSidebarItemLink | PropSidebarItemCategory}): JSX.Element {
|
||||
let icon: ReactNode;
|
||||
|
||||
if (item.customProps?.docCardIconName) {
|
||||
const iconName = item.customProps.docCardIconName;
|
||||
icon = <img alt={`${iconName} icon`} src={useBaseUrl(`/img/icons/${iconName}.svg`)}/>
|
||||
} else {
|
||||
icon = item.type === 'category' ? '🗃️' : isInternalUrl(item.href) ? '📄️' : '🔗';
|
||||
}
|
||||
|
||||
return (
|
||||
<div className={styles.cardIcon}>
|
||||
{icon}
|
||||
</div>
|
||||
)
|
||||
}
|
||||
37
docs/src/theme/DocCard/styles.module.css
Normal file
@ -0,0 +1,37 @@
|
||||
.cardContainer {
|
||||
--ifm-link-color: var(--ifm-color-emphasis-800);
|
||||
--ifm-link-hover-color: var(--ifm-color-emphasis-700);
|
||||
--ifm-link-hover-decoration: none;
|
||||
|
||||
box-shadow: 0 1.5px 3px 0 rgb(0 0 0 / 15%);
|
||||
border: 1px solid var(--ifm-color-emphasis-200);
|
||||
transition: all var(--ifm-transition-fast) ease;
|
||||
transition-property: border, box-shadow;
|
||||
}
|
||||
|
||||
.cardContainer:hover {
|
||||
border-color: var(--ifm-color-primary);
|
||||
box-shadow: 0 3px 6px 0 rgb(0 0 0 / 20%);
|
||||
}
|
||||
|
||||
.cardContainer *:last-child {
|
||||
margin-bottom: 0;
|
||||
}
|
||||
|
||||
.cardTitle {
|
||||
font-size: 1.2rem;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
.cardDescription {
|
||||
font-size: 0.8rem;
|
||||
}
|
||||
|
||||
.cardIcon {
|
||||
margin-right: 1rem;
|
||||
width: 2rem;
|
||||
height: 2rem;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
}
|
||||
0
docs/static/.nojekyll
vendored
Normal file
BIN
docs/static/img/favicon.ico
vendored
Normal file
|
After Width: | Height: | Size: 15 KiB |
12
docs/static/img/icons/angular.svg
vendored
Normal file
@ -0,0 +1,12 @@
|
||||
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" version="1.1" id="Layer_1" x="0px" y="0px" style="enable-background:new 0 0 250 250;" xml:space="preserve" viewBox="31.9 30 186.2 200">
|
||||
<style type="text/css">
|
||||
.st0{fill:#DD0031;}
|
||||
.st1{fill:#C3002F;}
|
||||
.st2{fill:#FFFFFF;}
|
||||
</style>
|
||||
<g>
|
||||
<polygon class="st0" points="125,30 125,30 125,30 31.9,63.2 46.1,186.3 125,230 125,230 125,230 203.9,186.3 218.1,63.2 "/>
|
||||
<polygon class="st1" points="125,30 125,52.2 125,52.1 125,153.4 125,153.4 125,230 125,230 203.9,186.3 218.1,63.2 125,30 "/>
|
||||
<path class="st2" d="M125,52.1L66.8,182.6h0h21.7h0l11.7-29.2h49.4l11.7,29.2h0h21.7h0L125,52.1L125,52.1L125,52.1L125,52.1 L125,52.1z M142,135.4H108l17-40.9L142,135.4z"/>
|
||||
</g>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 752 B |
3
docs/static/img/icons/nextjs-dark.svg
vendored
Normal file
@ -0,0 +1,3 @@
|
||||
<svg width="1000" height="1000" viewBox="0 0 1000 1000" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||
<path d="M467.253 0.269139C465.103 0.464613 458.26 1.14878 452.102 1.63747C310.068 14.4411 177.028 91.0671 92.7664 208.841C45.8456 274.325 15.8358 348.605 4.49658 427.284C0.488759 454.748 0 462.86 0 500.098C0 537.336 0.488759 545.448 4.49658 572.912C31.6716 760.666 165.298 918.414 346.53 976.861C378.983 987.319 413.196 994.453 452.102 998.754C467.253 1000.42 532.747 1000.42 547.898 998.754C615.054 991.326 671.945 974.71 728.055 946.073C736.657 941.675 738.319 940.502 737.146 939.525C736.364 938.939 699.707 889.777 655.718 830.352L575.758 722.353L475.562 574.085C420.43 492.572 375.073 425.915 374.682 425.915C374.291 425.818 373.9 491.693 373.705 572.13C373.412 712.97 373.314 718.639 371.554 721.962C369.013 726.751 367.058 728.706 362.952 730.856C359.824 732.42 357.087 732.713 342.327 732.713H325.415L320.919 729.878C317.986 728.021 315.836 725.578 314.37 722.744L312.317 718.345L312.512 522.382L312.805 326.321L315.836 322.509C317.4 320.457 320.723 317.818 323.069 316.547C327.077 314.592 328.641 314.397 345.552 314.397C365.494 314.397 368.817 315.179 373.998 320.848C375.464 322.411 429.717 404.12 494.624 502.541C559.531 600.963 648.289 735.352 691.887 801.324L771.065 921.248L775.073 918.609C810.557 895.543 848.094 862.703 877.81 828.495C941.056 755.877 981.818 667.326 995.503 572.912C999.511 545.448 1000 537.336 1000 500.098C1000 462.86 999.511 454.748 995.503 427.284C968.328 239.53 834.702 81.7821 653.47 23.3352C621.505 12.975 587.488 5.84016 549.365 1.53972C539.98 0.562345 475.367 -0.51276 467.253 0.269139ZM671.945 302.668C676.637 305.014 680.45 309.51 681.818 314.201C682.6 316.743 682.796 371.085 682.6 493.549L682.307 669.281L651.32 621.781L620.235 574.281V446.538C620.235 363.95 620.626 317.525 621.212 315.277C622.776 309.803 626.197 305.503 630.89 302.962C634.897 300.909 636.364 300.714 651.711 300.714C666.178 300.714 668.719 300.909 671.945 302.668Z" fill="white"/>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 2.0 KiB |
37
docs/static/img/icons/react.svg
vendored
Normal file
@ -0,0 +1,37 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<!-- Generator: Adobe Illustrator 25.2.0, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
|
||||
<svg version="1.1" id="Layer_2_1_" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
|
||||
viewBox="0 0 490.6 436.9" style="enable-background:new 0 0 490.6 436.9;" xml:space="preserve">
|
||||
<style type="text/css">
|
||||
.st0{fill:#61DAFB;}
|
||||
</style>
|
||||
<g>
|
||||
<path class="st0" d="M490.6,218.5c0-32.5-40.7-63.3-103.1-82.4c14.4-63.6,8-114.2-20.2-130.4c-6.5-3.8-14.1-5.6-22.4-5.6v22.3
|
||||
c4.6,0,8.3,0.9,11.4,2.6c13.6,7.8,19.5,37.5,14.9,75.7c-1.1,9.4-2.9,19.3-5.1,29.4c-19.6-4.8-41-8.5-63.5-10.9
|
||||
c-13.5-18.5-27.5-35.3-41.6-50c32.6-30.3,63.2-46.9,84-46.9V0l0,0c-27.5,0-63.5,19.6-99.9,53.6c-36.4-33.8-72.4-53.2-99.9-53.2
|
||||
v22.3c20.7,0,51.4,16.5,84,46.6c-14,14.7-28,31.4-41.3,49.9c-22.6,2.4-44,6.1-63.6,11c-2.3-10-4-19.7-5.2-29
|
||||
c-4.7-38.2,1.1-67.9,14.6-75.8c3-1.8,6.9-2.6,11.5-2.6V0.5l0,0c-8.4,0-16,1.8-22.6,5.6c-28.1,16.2-34.4,66.7-19.9,130.1
|
||||
C40.5,155.4,0,186.1,0,218.5c0,32.5,40.7,63.3,103.1,82.4c-14.4,63.6-8,114.2,20.2,130.4c6.5,3.8,14.1,5.6,22.5,5.6
|
||||
c27.5,0,63.5-19.6,99.9-53.6c36.4,33.8,72.4,53.2,99.9,53.2c8.4,0,16-1.8,22.6-5.6c28.1-16.2,34.4-66.7,19.9-130.1
|
||||
C450.1,281.7,490.6,250.9,490.6,218.5z M360.4,151.8c-3.7,12.9-8.3,26.2-13.5,39.5c-4.1-8-8.4-16-13.1-24
|
||||
c-4.6-8-9.5-15.8-14.4-23.4C333.6,146,347.3,148.6,360.4,151.8z M314.6,258.3c-7.8,13.5-15.8,26.3-24.1,38.2c-14.9,1.3-30,2-45.2,2
|
||||
c-15.1,0-30.2-0.7-45-1.9c-8.3-11.9-16.4-24.6-24.2-38c-7.6-13.1-14.5-26.4-20.8-39.8c6.2-13.4,13.2-26.8,20.7-39.9
|
||||
c7.8-13.5,15.8-26.3,24.1-38.2c14.9-1.3,30-2,45.2-2c15.1,0,30.2,0.7,45,1.9c8.3,11.9,16.4,24.6,24.2,38
|
||||
c7.6,13.1,14.5,26.4,20.8,39.8C329,231.8,322.1,245.2,314.6,258.3z M346.9,245.3c5.4,13.4,10,26.8,13.8,39.8
|
||||
c-13.1,3.2-26.9,5.9-41.2,8c4.9-7.7,9.8-15.6,14.4-23.7C338.5,261.4,342.8,253.3,346.9,245.3z M245.5,352
|
||||
c-9.3-9.6-18.6-20.3-27.8-32c9,0.4,18.2,0.7,27.5,0.7c9.4,0,18.7-0.2,27.8-0.7C264,331.7,254.7,342.4,245.5,352z M171.1,293.1
|
||||
c-14.2-2.1-27.9-4.7-41-7.9c3.7-12.9,8.3-26.2,13.5-39.5c4.1,8,8.4,16,13.1,24S166.2,285.5,171.1,293.1z M245,85
|
||||
c9.3,9.6,18.6,20.3,27.8,32c-9-0.4-18.2-0.7-27.5-0.7c-9.4,0-18.7,0.2-27.8,0.7C226.5,105.3,235.8,94.6,245,85z M171,143.9
|
||||
c-4.9,7.7-9.8,15.6-14.4,23.7c-4.6,8-8.9,16-13,24c-5.4-13.4-10-26.8-13.8-39.8C142.9,148.7,156.7,146,171,143.9z M80.5,269.1
|
||||
c-35.4-15.1-58.3-34.9-58.3-50.6s22.9-35.6,58.3-50.6c8.6-3.7,18-7,27.7-10.1c5.7,19.6,13.2,40,22.5,60.9
|
||||
c-9.2,20.8-16.6,41.1-22.2,60.6C98.6,276.2,89.2,272.8,80.5,269.1z M134.3,412c-13.6-7.8-19.5-37.5-14.9-75.7
|
||||
c1.1-9.4,2.9-19.3,5.1-29.4c19.6,4.8,41,8.5,63.5,10.9c13.5,18.5,27.5,35.3,41.6,50c-32.6,30.3-63.2,46.9-84,46.9
|
||||
C141.1,414.6,137.3,413.7,134.3,412z M371.5,335.8c4.7,38.2-1.1,67.9-14.6,75.8c-3,1.8-6.9,2.6-11.5,2.6c-20.7,0-51.4-16.5-84-46.6
|
||||
c14-14.7,28-31.4,41.3-49.9c22.6-2.4,44-6.1,63.6-11C368.6,316.8,370.4,326.5,371.5,335.8z M410,269.1c-8.6,3.7-18,7-27.7,10.1
|
||||
c-5.7-19.6-13.2-40-22.5-60.9c9.2-20.8,16.6-41.1,22.2-60.6c9.9,3.1,19.3,6.5,28.1,10.2c35.4,15.1,58.3,34.9,58.3,50.6
|
||||
C468.3,234.2,445.4,254.1,410,269.1z"/>
|
||||
<path class="st0" d="M145.1,0.4L145.1,0.4L145.1,0.4z"/>
|
||||
<circle class="st0" cx="245.2" cy="218.5" r="45.7"/>
|
||||
<path class="st0" d="M344.8,0.1L344.8,0.1L344.8,0.1z"/>
|
||||
</g>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 3.2 KiB |
2
docs/static/img/icons/vue.svg
vendored
Normal file
@ -0,0 +1,2 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<svg version="1.1" viewBox="0 0 261.76 226.69" xmlns="http://www.w3.org/2000/svg"><g transform="matrix(1.3333 0 0 -1.3333 -76.311 313.34)"><g transform="translate(178.06 235.01)"><path d="m0 0-22.669-39.264-22.669 39.264h-75.491l98.16-170.02 98.16 170.02z" fill="#41b883"/></g><g transform="translate(178.06 235.01)"><path d="m0 0-22.669-39.264-22.669 39.264h-36.227l58.896-102.01 58.896 102.01z" fill="#34495e"/></g></g></svg>
|
||||
|
After Width: | Height: | Size: 467 B |
11
docs/static/img/logo.svg
vendored
Normal file
@ -0,0 +1,11 @@
|
||||
<svg width="105" height="35" viewBox="0 0 105 35" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||
<path d="M28.0484 9.32422V30.3777H24.9845V18.8524C24.9845 18.8524 16.9031 18.8524 12.8772 18.8524C12.8772 19.8094 12.8772 20.7109 12.8772 21.6956C15.9262 21.6956 18.8865 21.6956 21.9207 21.6956C21.9207 22.2504 21.9207 22.708 21.9207 23.1657C21.9207 26.8411 21.9207 30.5303 21.9207 34.2057C21.9207 34.4414 21.9355 34.6217 21.9651 34.7604C25.399 34.2334 28.522 32.8465 31.0678 30.8216C31.0678 27.9368 31.0678 16.5917 31.0678 16.0092C31.053 13.804 30.5202 11.3491 28.0484 9.32422Z" fill="#FF2E4C"/>
|
||||
<path d="M21.9058 10.2117H24.9696V3.90117C26.8197 4.27564 33.8207 8.56124 34.1019 15.2878V27.7702C36.3665 24.8576 37.7134 21.2793 37.7134 17.396C37.7134 8.63058 30.8901 1.36309 21.9502 0.00390625C21.9206 0.156468 21.9058 0.336768 21.9058 0.572546L21.9058 10.2117Z" fill="#FF2E4C"/>
|
||||
<path d="M9.79849 25.4401V4.38659H12.8623V15.9119C12.8623 15.9119 20.9438 15.9119 24.9697 15.9119C24.9697 14.955 24.9697 14.0535 24.9697 13.0687C21.9206 13.0687 18.9604 13.0687 15.9262 13.0687C15.9262 12.514 15.9262 12.0563 15.9262 11.5986C15.9262 7.92325 15.9262 4.23403 15.9262 0.558676C15.9262 0.322899 15.9114 0.142599 15.8818 0.00390625C12.4479 0.530938 9.32485 1.91786 6.77905 3.94277C6.77905 6.82758 6.77905 18.1726 6.77905 18.7551C6.79385 20.9742 7.3267 23.4291 9.79849 25.4401Z" fill="#FF2E4C"/>
|
||||
<path d="M15.9409 24.5663H12.8771V30.8768C11.027 30.5023 4.026 26.2167 3.74478 19.4901V7.00781C1.48021 9.92036 0.133301 13.4986 0.133301 17.382C0.133301 26.1474 6.95663 33.4149 15.8965 34.7741C15.9261 34.6215 15.9409 34.4412 15.9409 34.2054V24.5663Z" fill="#FF2E4C"/>
|
||||
<path d="M47.7273 24.9719V9.25977H50.1504V15.6112H52.3238V9.25977H54.7469V24.9719H52.3238V17.6656H50.1504V24.9719H47.7273Z" fill="white"/>
|
||||
<path fill-rule="evenodd" clip-rule="evenodd" d="M62.2071 9.25977L59.9309 24.9719H62.2952L62.633 22.1652H65.2029L65.5848 24.9719H67.8463L65.4085 9.25977H62.2071ZM63.8666 12.3414L64.9386 20.2409H62.8533L63.8372 12.3414H63.8666Z" fill="white"/>
|
||||
<path d="M73.0154 24.9719V9.25977H74.9245L78.3021 18.6929L78.1259 14.4103V9.27423H80.314V24.9864H78.5958L75.1301 15.2206L75.2622 19.3439V24.9719H73.0154Z" fill="white"/>
|
||||
<path d="M85.8503 24.9719V9.25977H88.2734V16.4937L90.6965 9.25977H93.2077L90.5643 17.0146L93.4133 24.9719H90.8433L88.3028 17.6222V24.9575H85.8503V24.9719Z" fill="white"/>
|
||||
<path fill-rule="evenodd" clip-rule="evenodd" d="M101.358 25.145C102.592 25.145 103.473 24.7688 104.031 24.0165C104.589 23.2497 104.868 22.1067 104.868 20.5731V13.3826C104.868 11.9647 104.603 10.8941 104.06 10.1562C103.517 9.41834 102.636 9.05664 101.402 9.05664C99.0084 9.05664 97.8188 10.5034 97.8188 13.3826V20.5731C97.8188 22.0922 98.0979 23.2497 98.6706 24.002C99.2433 24.7688 100.139 25.145 101.358 25.145ZM101.358 23.0761C100.917 23.0761 100.624 22.888 100.477 22.5263C100.345 22.1646 100.271 21.528 100.257 20.602V13.2668C100.257 12.5289 100.345 11.9936 100.506 11.6464C100.668 11.3136 100.962 11.14 101.373 11.14C101.784 11.14 102.063 11.2992 102.21 11.6464C102.357 11.9936 102.43 12.5434 102.43 13.2813V20.602C102.43 21.4991 102.357 22.1356 102.224 22.5118C102.092 22.888 101.799 23.0761 101.358 23.0761Z" fill="white"/>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 3.1 KiB |
BIN
docs/static/img/thumbnail.jpg
vendored
Normal file
|
After Width: | Height: | Size: 93 KiB |
7
docs/tsconfig.json
Normal file
@ -0,0 +1,7 @@
|
||||
{
|
||||
// This file is not used in compilation. It is here just for a nice editor experience.
|
||||
"extends": "@tsconfig/docusaurus/tsconfig.json",
|
||||
"compilerOptions": {
|
||||
"baseUrl": "."
|
||||
}
|
||||
}
|
||||
@ -23,7 +23,7 @@
|
||||
"format": "pretty-quick --staged",
|
||||
"build": "microbundle --globals @github/webauthn-json=webauthnJson --tsconfig ./tsconfig.json",
|
||||
"dev": "microbundle watch",
|
||||
"docs": "jsdoc -r -c jsdoc.json -d ../docs/jsdoc -P package.json -R README.md --pedantic"
|
||||
"docs": "jsdoc -r -c jsdoc.json -d ../docs/static/jsdoc -P package.json -R README.md --pedantic"
|
||||
},
|
||||
"description": "A package for simplifying UI integration with the Hanko API. It is meant for use in browsers only.",
|
||||
"repository": "github:teamhanko/hanko",
|
||||
|
||||