drab 1.9.3

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,81 @@
1
+ <!--
2
+ @component
3
+
4
+ ### FullscreenButton
5
+
6
+ Make the document or a specific element fullscreen.
7
+
8
+ @props
9
+
10
+ - `class`
11
+ - `confirmMessage` - message to display in the `confirm` popup, set this to empty string `""` to disable `confirm`
12
+ - `id`
13
+ - `targetElement` - element to make fullscreen (defaults to `document.documentElement` upon mount)
14
+ - `title`
15
+
16
+ @slots
17
+
18
+ | name | purpose | default value |
19
+ | ---------- | ---------------------------------------------- | -------------------- |
20
+ | `enabled` | content to display when fullscreen is enabled | `Exit Fullscreen` |
21
+ | `disabled` | content to display when fullscreen is disabled | `Enabled Fullscreen` |
22
+
23
+ @example
24
+
25
+ ```svelte
26
+ <script>
27
+ import { FullscreenButton } from "@rossrobino/components";
28
+
29
+ let fullscreenDiv;
30
+ </script>
31
+
32
+ <FullscreenButton />
33
+
34
+ <div bind:this={fullscreenDiv}>
35
+ <div>Target element fullscreen</div>
36
+ <FullscreenButton targetElement={fullscreenDiv}>
37
+ <span slot="enabled">Exit Element Fullscreen</span>
38
+ <span slot="disabled">Enable Element Fullscreen</span>
39
+ </FullscreenButton>
40
+ </div>
41
+ ```
42
+ -->
43
+
44
+ <script>import { onMount } from "svelte";
45
+ let className = "";
46
+ export { className as class };
47
+ export let id = "";
48
+ export let title = "Fullscreen";
49
+ export let targetElement = null;
50
+ export let confirmMessage = "";
51
+ let fullscreen = false;
52
+ onMount(() => {
53
+ if (!targetElement)
54
+ targetElement = document.documentElement;
55
+ });
56
+ const onClick = () => {
57
+ if (fullscreen) {
58
+ document.exitFullscreen();
59
+ } else {
60
+ if (targetElement && targetElement.requestFullscreen) {
61
+ if (confirmMessage) {
62
+ const permission = confirm(confirmMessage);
63
+ if (permission)
64
+ targetElement.requestFullscreen();
65
+ } else {
66
+ targetElement.requestFullscreen();
67
+ }
68
+ }
69
+ }
70
+ };
71
+ </script>
72
+
73
+ <svelte:window on:fullscreenchange={() => (fullscreen = !fullscreen)} />
74
+
75
+ <button on:click={onClick} class={className} {id} {title}>
76
+ {#if fullscreen}
77
+ <slot name="enabled">Exit Fullscreen</slot>
78
+ {:else}
79
+ <slot name="disabled">Enable Fullscreen</slot>
80
+ {/if}
81
+ </button>
@@ -0,0 +1,63 @@
1
+ import { SvelteComponent } from "svelte";
2
+ declare const __propDef: {
3
+ props: {
4
+ class?: string | undefined;
5
+ id?: string | undefined;
6
+ title?: string | undefined;
7
+ /** element to make fullscreen (defaults to `document.documentElement` upon mount) */ targetElement?: HTMLElement | null | undefined;
8
+ /** message to display in the `confirm` popup, set this to empty string `""` to disable `confirm` */ confirmMessage?: string | undefined;
9
+ };
10
+ events: {
11
+ [evt: string]: CustomEvent<any>;
12
+ };
13
+ slots: {
14
+ enabled: {};
15
+ disabled: {};
16
+ };
17
+ };
18
+ export type FullscreenButtonProps = typeof __propDef.props;
19
+ export type FullscreenButtonEvents = typeof __propDef.events;
20
+ export type FullscreenButtonSlots = typeof __propDef.slots;
21
+ /**
22
+ * ### FullscreenButton
23
+ *
24
+ * Make the document or a specific element fullscreen.
25
+ *
26
+ * @props
27
+ *
28
+ * - `class`
29
+ * - `confirmMessage` - message to display in the `confirm` popup, set this to empty string `""` to disable `confirm`
30
+ * - `id`
31
+ * - `targetElement` - element to make fullscreen (defaults to `document.documentElement` upon mount)
32
+ * - `title`
33
+ *
34
+ * @slots
35
+ *
36
+ * | name | purpose | default value |
37
+ * | ---------- | ---------------------------------------------- | -------------------- |
38
+ * | `enabled` | content to display when fullscreen is enabled | `Exit Fullscreen` |
39
+ * | `disabled` | content to display when fullscreen is disabled | `Enabled Fullscreen` |
40
+ *
41
+ * @example
42
+ *
43
+ * ```svelte
44
+ * <script>
45
+ * import { FullscreenButton } from "@rossrobino/components";
46
+ *
47
+ * let fullscreenDiv;
48
+ * </script>
49
+ *
50
+ * <FullscreenButton />
51
+ *
52
+ * <div bind:this={fullscreenDiv}>
53
+ * <div>Target element fullscreen</div>
54
+ * <FullscreenButton targetElement={fullscreenDiv}>
55
+ * <span slot="enabled">Exit Element Fullscreen</span>
56
+ * <span slot="disabled">Enable Element Fullscreen</span>
57
+ * </FullscreenButton>
58
+ * </div>
59
+ * ```
60
+ */
61
+ export default class FullscreenButton extends SvelteComponent<FullscreenButtonProps, FullscreenButtonEvents, FullscreenButtonSlots> {
62
+ }
63
+ export {};
@@ -0,0 +1,66 @@
1
+ <!--
2
+ @component
3
+
4
+ ### ShareButton
5
+
6
+ Uses the navigator api to share or copy a url link depending on browser support.
7
+
8
+ @props
9
+
10
+ - `class`
11
+ - `id`
12
+ - `text` - prefixed text in share message
13
+ - `title` - title of share message and button attribute
14
+ - `url` - url to be shared
15
+
16
+ @slots
17
+
18
+ | name | purpose | default value |
19
+ | ---------- | ------------------------------- | ------------- |
20
+ | `default` | default | `Share` |
21
+ | `complete` | displays after copy is complete | `Copied` |
22
+
23
+ @example
24
+
25
+ ```svelte
26
+ <script>
27
+ import { ShareButton } from "@rossrobino/components";
28
+ </script>
29
+
30
+ <ShareButton
31
+ text="Check out this page: "
32
+ title="@rossrobino/components"
33
+ url="https://components.robino.dev"
34
+ />
35
+ ```
36
+ -->
37
+
38
+ <script>let className = "";
39
+ export { className as class };
40
+ export let id = "";
41
+ export let text = "";
42
+ export let url;
43
+ export let title = url.split("/").splice(-1)[0];
44
+ let complete = false;
45
+ const onClick = async () => {
46
+ try {
47
+ if (navigator.canShare) {
48
+ await navigator.share({ text, url, title });
49
+ } else {
50
+ await navigator.clipboard.writeText(url);
51
+ complete = true;
52
+ setTimeout(() => complete = false, 800);
53
+ }
54
+ } catch (error) {
55
+ console.log(error);
56
+ }
57
+ };
58
+ </script>
59
+
60
+ <button on:click={onClick} class={className} {id} {title}>
61
+ {#if complete}
62
+ <slot name="complete">Copied</slot>
63
+ {:else}
64
+ <slot>Share</slot>
65
+ {/if}
66
+ </button>
@@ -0,0 +1,57 @@
1
+ import { SvelteComponent } from "svelte";
2
+ declare const __propDef: {
3
+ props: {
4
+ class?: string | undefined;
5
+ id?: string | undefined;
6
+ /** prefixed text in share message */ text?: string | undefined;
7
+ /** url to be shared */ url: string;
8
+ /** title of share message and button attribute */ title?: string | undefined;
9
+ };
10
+ events: {
11
+ [evt: string]: CustomEvent<any>;
12
+ };
13
+ slots: {
14
+ complete: {};
15
+ default: {};
16
+ };
17
+ };
18
+ export type ShareButtonProps = typeof __propDef.props;
19
+ export type ShareButtonEvents = typeof __propDef.events;
20
+ export type ShareButtonSlots = typeof __propDef.slots;
21
+ /**
22
+ * ### ShareButton
23
+ *
24
+ * Uses the navigator api to share or copy a url link depending on browser support.
25
+ *
26
+ * @props
27
+ *
28
+ * - `class`
29
+ * - `id`
30
+ * - `text` - prefixed text in share message
31
+ * - `title` - title of share message and button attribute
32
+ * - `url` - url to be shared
33
+ *
34
+ * @slots
35
+ *
36
+ * | name | purpose | default value |
37
+ * | ---------- | ------------------------------- | ------------- |
38
+ * | `default` | default | `Share` |
39
+ * | `complete` | displays after copy is complete | `Copied` |
40
+ *
41
+ * @example
42
+ *
43
+ * ```svelte
44
+ * <script>
45
+ * import { ShareButton } from "@rossrobino/components";
46
+ * </script>
47
+ *
48
+ * <ShareButton
49
+ * text="Check out this page: "
50
+ * title="@rossrobino/components"
51
+ * url="https://components.robino.dev"
52
+ * />
53
+ * ```
54
+ */
55
+ export default class ShareButton extends SvelteComponent<ShareButtonProps, ShareButtonEvents, ShareButtonSlots> {
56
+ }
57
+ export {};
@@ -0,0 +1,47 @@
1
+ <!--
2
+ @component
3
+
4
+ ### YouTube
5
+
6
+ Embeds a YouTube video into a website with the video `uid`, using [www.youtube-nocookie.com](https://support.google.com/youtube/answer/171780?hl=en#zippy=%2Cturn-on-privacy-enhanced-mode).
7
+
8
+ @props
9
+
10
+ - `autoplay` - auto-plays the video
11
+ - `class`
12
+ - `id`
13
+ - `start` - start time (seconds)
14
+ - `title`
15
+ - `uid` - unique YouTube id
16
+
17
+ @example
18
+
19
+ ```svelte
20
+ <script>
21
+ import { YouTube } from "@rossrobino/components";
22
+ </script>
23
+
24
+ <YouTube title="Video Title" uid="youtube_uid" />
25
+ ```
26
+ -->
27
+
28
+ <script>let className = "";
29
+ export { className as class };
30
+ export let id = "";
31
+ export let uid;
32
+ export let title = "";
33
+ export let autoplay = false;
34
+ export let start = 0;
35
+ </script>
36
+
37
+ <iframe
38
+ class={className}
39
+ {id}
40
+ src="https://www.youtube-nocookie.com/embed/{uid}?start={start}{autoplay
41
+ ? '&autoplay=1'
42
+ : ''}"
43
+ {title}
44
+ frameborder="0"
45
+ allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture"
46
+ allowfullscreen
47
+ />
@@ -0,0 +1,45 @@
1
+ import { SvelteComponent } from "svelte";
2
+ declare const __propDef: {
3
+ props: {
4
+ class?: string | undefined;
5
+ id?: string | undefined;
6
+ /** unique YouTube id */ uid: string;
7
+ title?: string | undefined;
8
+ /** auto-plays the video */ autoplay?: boolean | undefined;
9
+ /** start time (seconds) */ start?: number | undefined;
10
+ };
11
+ events: {
12
+ [evt: string]: CustomEvent<any>;
13
+ };
14
+ slots: {};
15
+ };
16
+ export type YouTubeProps = typeof __propDef.props;
17
+ export type YouTubeEvents = typeof __propDef.events;
18
+ export type YouTubeSlots = typeof __propDef.slots;
19
+ /**
20
+ * ### YouTube
21
+ *
22
+ * Embeds a YouTube video into a website with the video `uid`, using [www.youtube-nocookie.com](https://support.google.com/youtube/answer/171780?hl=en#zippy=%2Cturn-on-privacy-enhanced-mode).
23
+ *
24
+ * @props
25
+ *
26
+ * - `autoplay` - auto-plays the video
27
+ * - `class`
28
+ * - `id`
29
+ * - `start` - start time (seconds)
30
+ * - `title`
31
+ * - `uid` - unique YouTube id
32
+ *
33
+ * @example
34
+ *
35
+ * ```svelte
36
+ * <script>
37
+ * import { YouTube } from "@rossrobino/components";
38
+ * </script>
39
+ *
40
+ * <YouTube title="Video Title" uid="youtube_uid" />
41
+ * ```
42
+ */
43
+ export default class YouTube extends SvelteComponent<YouTubeProps, YouTubeEvents, YouTubeSlots> {
44
+ }
45
+ export {};
@@ -0,0 +1,10 @@
1
+ import Chord from "./components/Chord.svelte";
2
+ import CopyButton from "./components/CopyButton.svelte";
3
+ import DataTable from "./components/DataTable.svelte";
4
+ import type { DataTableRow } from "./components/DataTable.svelte";
5
+ import Editor from "./components/Editor.svelte";
6
+ import type { EditorContentElement } from "./components/Editor.svelte";
7
+ import FullscreenButton from "./components/FullscreenButton.svelte";
8
+ import ShareButton from "./components/ShareButton.svelte";
9
+ import YouTube from "./components/YouTube.svelte";
10
+ export { Chord, CopyButton, DataTable, type DataTableRow, Editor, type EditorContentElement, FullscreenButton, ShareButton, YouTube, };
package/dist/index.js ADDED
@@ -0,0 +1,8 @@
1
+ import Chord from "./components/Chord.svelte";
2
+ import CopyButton from "./components/CopyButton.svelte";
3
+ import DataTable from "./components/DataTable.svelte";
4
+ import Editor from "./components/Editor.svelte";
5
+ import FullscreenButton from "./components/FullscreenButton.svelte";
6
+ import ShareButton from "./components/ShareButton.svelte";
7
+ import YouTube from "./components/YouTube.svelte";
8
+ export { Chord, CopyButton, DataTable, Editor, FullscreenButton, ShareButton, YouTube, };
@@ -0,0 +1 @@
1
+ export {};
@@ -0,0 +1,3 @@
1
+ import { documentPropsDir } from "./documentProps.js";
2
+
3
+ documentPropsDir("./src/lib/components");
@@ -0,0 +1,2 @@
1
+ export function documentPropsDir(dir: string): Promise<void>;
2
+ export function documentProps(path: string): Promise<void>;
@@ -0,0 +1,86 @@
1
+ import fs from "fs/promises";
2
+ import path from "path";
3
+
4
+ /**
5
+ * Runs `documentProps` over a given directory
6
+ *
7
+ * @param {string} dir path to directory
8
+ */
9
+ export const documentPropsDir = async (dir) => {
10
+ const files = await fs.readdir(dir);
11
+ for (const file of files) {
12
+ if (path.extname(file) === ".svelte") {
13
+ documentProps(path.join(dir, file));
14
+ }
15
+ }
16
+ };
17
+
18
+ /**
19
+ * - Finds "@props" in a component
20
+ * - If found, overwrites the docs with the generated docs
21
+ *
22
+ * @param {string} path path to component
23
+ */
24
+ export const documentProps = async (path) => {
25
+ const code = await fs.readFile(path, "utf-8");
26
+ const lines = code.split("\n");
27
+ const docs = getPropDocs(lines);
28
+ for (let i = 0; i < lines.length; i++) {
29
+ const line = lines[i].trim();
30
+ if (line.startsWith("@props")) {
31
+ for (let j = i + 1; j < lines.length; j++) {
32
+ // for the following lines...
33
+ const checkLine = lines[j].trim();
34
+ if (
35
+ checkLine.startsWith("@") ||
36
+ checkLine.startsWith("-->") ||
37
+ checkLine.startsWith("#") ||
38
+ checkLine.startsWith("|")
39
+ ) {
40
+ // delete current / add new
41
+ lines.splice(i + 1, j - i - 1, docs);
42
+ // join back together
43
+ const documented = lines.join("\n");
44
+ await fs.writeFile(path, documented);
45
+ console.log("Documented " + path);
46
+ break;
47
+ }
48
+ }
49
+ break;
50
+ }
51
+ if (i === lines.length - 1) {
52
+ // last line
53
+ console.log("No `@props` found for " + path);
54
+ }
55
+ }
56
+ };
57
+
58
+ /**
59
+ * - Finds the props and JSDoc comments
60
+ *
61
+ * @param {string[]} lines lines of code
62
+ */
63
+ const getPropDocs = (lines) => {
64
+ const docs = ["\n"];
65
+ for (let i = 0; i < lines.length; i++) {
66
+ const line = lines[i].trim();
67
+ const isClass = line === "export { className as class };";
68
+ if (line.startsWith("export let ") || isClass) {
69
+ let propName = line.split(" ")[2];
70
+ if (isClass) {
71
+ propName = "class";
72
+ }
73
+ if (propName.endsWith(":")) propName = propName.slice(0, -1);
74
+ const previousLine = lines[i - 1].trim();
75
+ let jsDoc = "";
76
+ if (previousLine.endsWith("*/")) {
77
+ if (previousLine.startsWith("/**")) {
78
+ jsDoc = "- " + previousLine.slice(3, -2).trim();
79
+ }
80
+ }
81
+ docs.push(`- \`${propName}\` ${jsDoc}\n`);
82
+ }
83
+ }
84
+ docs.sort();
85
+ return docs.join("");
86
+ };
package/package.json ADDED
@@ -0,0 +1,74 @@
1
+ {
2
+ "name": "drab",
3
+ "version": "1.9.3",
4
+ "description": "An unstyled Svelte component library",
5
+ "keywords": [
6
+ "components",
7
+ "Svelte",
8
+ "SvelteKit",
9
+ "Chord",
10
+ "Copy",
11
+ "DataTable",
12
+ "Editor",
13
+ "Fullscreen",
14
+ "Share",
15
+ "YouTube"
16
+ ],
17
+ "homepage": "https://drab.robino.dev",
18
+ "license": "MIT",
19
+ "author": {
20
+ "name": "Ross Robino",
21
+ "url": "https://robino.dev"
22
+ },
23
+ "repository": "github:rossrobino/drab",
24
+ "scripts": {
25
+ "dev": "vite dev",
26
+ "build": "node src/lib/util/buildDocs.js && vite build && npm run package",
27
+ "preview": "vite preview",
28
+ "package": "svelte-kit sync && svelte-package && publint",
29
+ "prepublishOnly": "npm run package",
30
+ "check": "svelte-kit sync && svelte-check --tsconfig ./tsconfig.json",
31
+ "check:watch": "svelte-kit sync && svelte-check --tsconfig ./tsconfig.json --watch",
32
+ "lint": "prettier --check . && eslint .",
33
+ "format": "prettier --write . --plugin=prettier-plugin-svelte --plugin=prettier-plugin-tailwindcss",
34
+ "pub": "npm publish --access public"
35
+ },
36
+ "exports": {
37
+ ".": {
38
+ "types": "./dist/index.d.ts",
39
+ "svelte": "./dist/index.js"
40
+ }
41
+ },
42
+ "files": [
43
+ "dist"
44
+ ],
45
+ "dependencies": {
46
+ "svelte": "^4.1.2"
47
+ },
48
+ "devDependencies": {
49
+ "@sveltejs/adapter-vercel": "^3.0.3",
50
+ "@sveltejs/kit": "^1.22.4",
51
+ "@sveltejs/package": "^2.2.0",
52
+ "@tailwindcss/typography": "^0.5.9",
53
+ "@types/node": "^20.4.9",
54
+ "@typescript-eslint/eslint-plugin": "^6.3.0",
55
+ "@typescript-eslint/parser": "^6.3.0",
56
+ "autoprefixer": "^10.4.14",
57
+ "eslint": "^8.46.0",
58
+ "eslint-config-prettier": "^9.0.0",
59
+ "eslint-plugin-svelte": "^2.32.4",
60
+ "postcss": "^8.4.27",
61
+ "prettier": "^3.0.1",
62
+ "prettier-plugin-svelte": "^3.0.3",
63
+ "prettier-plugin-tailwindcss": "^0.4.1",
64
+ "publint": "^0.2.0",
65
+ "svelte-check": "^3.4.6",
66
+ "tailwindcss": "^3.3.3",
67
+ "tslib": "^2.6.1",
68
+ "typescript": "^5.1.6",
69
+ "vite": "^4.4.9"
70
+ },
71
+ "svelte": "./dist/index.js",
72
+ "types": "./dist/index.d.ts",
73
+ "type": "module"
74
+ }