@goblin-systems/goblin-design-system 0.1.0
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.
- package/README.md +152 -0
- package/dist/headless/dom.d.ts +12 -0
- package/dist/headless/modal.d.ts +57 -0
- package/dist/headless/navigation.d.ts +33 -0
- package/dist/headless/range.d.ts +28 -0
- package/dist/headless/search.d.ts +31 -0
- package/dist/headless/split-pane.d.ts +17 -0
- package/dist/headless/tabs.d.ts +13 -0
- package/dist/headless/toast.d.ts +9 -0
- package/dist/icons/index.d.ts +20 -0
- package/dist/index.cjs +5 -0
- package/dist/index.d.ts +21 -0
- package/dist/index.js +716 -0
- package/dist/platform/tauri-window.d.ts +7 -0
- package/dist/style.css +1 -0
- package/dist/waveform/waveform.d.ts +21 -0
- package/package.json +46 -0
- package/skills/SKILL.md +372 -0
package/README.md
ADDED
|
@@ -0,0 +1,152 @@
|
|
|
1
|
+
# @goblin-systems/goblin-design-system
|
|
2
|
+
|
|
3
|
+
Dark, sharp-edged design system for desktop apps. Built with vanilla TypeScript and CSS custom properties — no framework required. Optimised for Tauri apps but usable anywhere.
|
|
4
|
+
|
|
5
|
+
- Zero runtime framework dependencies
|
|
6
|
+
- Full TypeScript API with headless behaviour modules
|
|
7
|
+
- 1,900+ Lucide icons included
|
|
8
|
+
- CSS custom property token system
|
|
9
|
+
- Tauri window control utilities (optional)
|
|
10
|
+
|
|
11
|
+
---
|
|
12
|
+
|
|
13
|
+
## Installation
|
|
14
|
+
|
|
15
|
+
```bash
|
|
16
|
+
npm install @goblin-systems/goblin-design-system lucide
|
|
17
|
+
# or
|
|
18
|
+
bun add @goblin-systems/goblin-design-system lucide
|
|
19
|
+
```
|
|
20
|
+
|
|
21
|
+
`lucide` is a required peer dependency.
|
|
22
|
+
|
|
23
|
+
---
|
|
24
|
+
|
|
25
|
+
## Quick start
|
|
26
|
+
|
|
27
|
+
```ts
|
|
28
|
+
// 1. Import styles once in your app entry
|
|
29
|
+
import "@goblin-systems/goblin-design-system/style.css";
|
|
30
|
+
|
|
31
|
+
// 2. Import what you need
|
|
32
|
+
import {
|
|
33
|
+
applyIcons,
|
|
34
|
+
showToast,
|
|
35
|
+
bindTabs,
|
|
36
|
+
bindNavigation,
|
|
37
|
+
bindSearch,
|
|
38
|
+
bindRange,
|
|
39
|
+
openModal,
|
|
40
|
+
confirmModal,
|
|
41
|
+
bindSplitPaneResize,
|
|
42
|
+
setupWindowControls,
|
|
43
|
+
} from "@goblin-systems/goblin-design-system";
|
|
44
|
+
|
|
45
|
+
// 3. After any HTML containing <i data-lucide="..."> is in the DOM:
|
|
46
|
+
applyIcons();
|
|
47
|
+
```
|
|
48
|
+
|
|
49
|
+
---
|
|
50
|
+
|
|
51
|
+
## Components
|
|
52
|
+
|
|
53
|
+
| Component | CSS class(es) | TS function |
|
|
54
|
+
|---|---|---|
|
|
55
|
+
| Button | `secondary-btn` | — |
|
|
56
|
+
| Icon button | `icon-btn`, `icon-btn-sm/md/lg` | — |
|
|
57
|
+
| Tabs | `top-tab`, `document-tab` | `bindTabs` |
|
|
58
|
+
| Modal | `modal-backdrop`, `modal-card` | `openModal`, `confirmModal` |
|
|
59
|
+
| Toast | `app-toast` | `showToast` |
|
|
60
|
+
| Navigation | `nav-bar`, `nav-item`, `nav-dropdown` | `bindNavigation` |
|
|
61
|
+
| Search field | `search-field` | `bindSearch` |
|
|
62
|
+
| Double range | `range-slider` | `bindRange` |
|
|
63
|
+
| Split pane | `split-workspace` | `bindSplitPaneResize` |
|
|
64
|
+
| Scroll panel | `scroll-panel` | — |
|
|
65
|
+
| Status indicator | `status-indicator` | — |
|
|
66
|
+
| Badge | `badge` | — |
|
|
67
|
+
| Waveform | — | `drawWaveform` |
|
|
68
|
+
|
|
69
|
+
See [`skills/SKILL.md`](skills/SKILL.md) for full markup patterns and API signatures.
|
|
70
|
+
|
|
71
|
+
---
|
|
72
|
+
|
|
73
|
+
## Overriding tokens
|
|
74
|
+
|
|
75
|
+
All visual properties are CSS custom properties. Override them after importing the stylesheet:
|
|
76
|
+
|
|
77
|
+
```css
|
|
78
|
+
:root {
|
|
79
|
+
--accent: #00b4d8;
|
|
80
|
+
--bg: #0a0a0a;
|
|
81
|
+
}
|
|
82
|
+
```
|
|
83
|
+
|
|
84
|
+
Full token list: [`src/lib/tokens.css`](src/lib/tokens.css)
|
|
85
|
+
|
|
86
|
+
---
|
|
87
|
+
|
|
88
|
+
## Installing the Claude Code skill
|
|
89
|
+
|
|
90
|
+
The `skills/SKILL.md` file is a ready-to-use Claude Code skill that gives Claude full knowledge of every component, CSS class, and TypeScript API in this design system.
|
|
91
|
+
|
|
92
|
+
**Project skill** (applies to one repo):
|
|
93
|
+
|
|
94
|
+
```bash
|
|
95
|
+
mkdir -p .claude/commands
|
|
96
|
+
cp node_modules/@goblin-systems/goblin-design-system/skills/SKILL.md .claude/commands/goblin-ds.md
|
|
97
|
+
```
|
|
98
|
+
|
|
99
|
+
**Global skill** (available in all your projects):
|
|
100
|
+
|
|
101
|
+
```bash
|
|
102
|
+
mkdir -p ~/.claude/commands
|
|
103
|
+
cp node_modules/@goblin-systems/goblin-design-system/skills/SKILL.md ~/.claude/commands/goblin-ds.md
|
|
104
|
+
```
|
|
105
|
+
|
|
106
|
+
Then in any Claude Code session, invoke it with:
|
|
107
|
+
|
|
108
|
+
```
|
|
109
|
+
/goblin-ds
|
|
110
|
+
```
|
|
111
|
+
|
|
112
|
+
Claude will have full context on components, markup patterns, design tokens, and TypeScript APIs for the duration of that conversation.
|
|
113
|
+
|
|
114
|
+
---
|
|
115
|
+
|
|
116
|
+
## Running the demo app
|
|
117
|
+
|
|
118
|
+
The repository includes a live demo Tauri app that showcases every component.
|
|
119
|
+
|
|
120
|
+
```bash
|
|
121
|
+
git clone https://github.com/goblin-systems/goblin-design-system
|
|
122
|
+
cd goblin-design-system
|
|
123
|
+
bun install
|
|
124
|
+
bun run dev # start Vite dev server
|
|
125
|
+
bun run tauri dev # launch Tauri window (requires Rust toolchain)
|
|
126
|
+
```
|
|
127
|
+
|
|
128
|
+
---
|
|
129
|
+
|
|
130
|
+
## Building the library
|
|
131
|
+
|
|
132
|
+
```bash
|
|
133
|
+
bun run build:lib # outputs to dist/
|
|
134
|
+
bun run lint # TypeScript type check
|
|
135
|
+
```
|
|
136
|
+
|
|
137
|
+
---
|
|
138
|
+
|
|
139
|
+
## CI / Release
|
|
140
|
+
|
|
141
|
+
| Workflow | Trigger | What it does |
|
|
142
|
+
|---|---|---|
|
|
143
|
+
| CI | push / PR to `master` | type-check + build library |
|
|
144
|
+
| Release | manual dispatch | bump version (patch/minor/major), publish to npm, create GitHub release |
|
|
145
|
+
|
|
146
|
+
The release workflow requires an `NPM_TOKEN` secret set in GitHub repository settings (Settings → Secrets and variables → Actions).
|
|
147
|
+
|
|
148
|
+
---
|
|
149
|
+
|
|
150
|
+
## Licence
|
|
151
|
+
|
|
152
|
+
MIT
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
/** Resolve a required element by id. Throws if missing. */
|
|
2
|
+
export declare function byId<T extends HTMLElement>(id: string, doc?: Document): T;
|
|
3
|
+
/** Resolve an optional element by id. Returns null if missing. */
|
|
4
|
+
export declare function byIdOptional<T extends HTMLElement>(id: string, doc?: Document): T | null;
|
|
5
|
+
/** Resolve a required element by CSS selector. Throws if missing. */
|
|
6
|
+
export declare function qs<T extends HTMLElement>(selector: string, root?: ParentNode): T;
|
|
7
|
+
/** Resolve all elements matching a CSS selector. */
|
|
8
|
+
export declare function qsAll<T extends HTMLElement>(selector: string, root?: ParentNode): NodeListOf<T>;
|
|
9
|
+
/** Populate a <select> with string options. Disables it when the list is empty. */
|
|
10
|
+
export declare function populateSelectOptions(select: HTMLSelectElement, options: string[], preferred: string): void;
|
|
11
|
+
/** Toggle the disabled+opacity state of a container and its interactive children. */
|
|
12
|
+
export declare function setGroupDisabled(container: HTMLElement, disabled: boolean): void;
|
|
@@ -0,0 +1,57 @@
|
|
|
1
|
+
export interface ModalOptions {
|
|
2
|
+
/** The modal backdrop element (contains the card). */
|
|
3
|
+
backdrop: HTMLElement;
|
|
4
|
+
/** Close when clicking the backdrop outside the card. Default true. */
|
|
5
|
+
closeOnBackdrop?: boolean;
|
|
6
|
+
/** Close on Escape key. Default true. */
|
|
7
|
+
closeOnEscape?: boolean;
|
|
8
|
+
/** Called after the modal closes via any path. */
|
|
9
|
+
onClose?: () => void;
|
|
10
|
+
/** Called when the accept button is activated. */
|
|
11
|
+
onAccept?: () => void;
|
|
12
|
+
/** Called when the reject button or any dismiss action is invoked. */
|
|
13
|
+
onReject?: () => void;
|
|
14
|
+
/** CSS selector for the accept button within the backdrop. Default ".modal-btn-accept". */
|
|
15
|
+
acceptBtnSelector?: string;
|
|
16
|
+
/** CSS selector for the reject button(s) within the backdrop. Default ".modal-btn-reject". */
|
|
17
|
+
rejectBtnSelector?: string;
|
|
18
|
+
}
|
|
19
|
+
export interface ConfirmOptions {
|
|
20
|
+
/** Modal heading. */
|
|
21
|
+
title: string;
|
|
22
|
+
/** Body paragraph shown below the title. */
|
|
23
|
+
message?: string;
|
|
24
|
+
/** Label for the accept/primary action button. Default "Confirm". */
|
|
25
|
+
acceptLabel?: string;
|
|
26
|
+
/** Label for the reject/cancel button. Default "Cancel". */
|
|
27
|
+
rejectLabel?: string;
|
|
28
|
+
/**
|
|
29
|
+
* Visual variant of the accept button.
|
|
30
|
+
* - "default" — accent purple (safe actions)
|
|
31
|
+
* - "danger" — error red (destructive actions)
|
|
32
|
+
*/
|
|
33
|
+
variant?: "default" | "danger";
|
|
34
|
+
/** Close when clicking outside the card. Default true. */
|
|
35
|
+
closeOnBackdrop?: boolean;
|
|
36
|
+
/** Close on Escape (counts as reject). Default true. */
|
|
37
|
+
closeOnEscape?: boolean;
|
|
38
|
+
}
|
|
39
|
+
export declare function openModal(options: ModalOptions): void;
|
|
40
|
+
export declare function closeModal(options: {
|
|
41
|
+
backdrop: HTMLElement;
|
|
42
|
+
onClose?: () => void;
|
|
43
|
+
}): void;
|
|
44
|
+
/**
|
|
45
|
+
* Wire a trigger button and optional close/reject/accept buttons to a modal
|
|
46
|
+
* backdrop by element ids.
|
|
47
|
+
*/
|
|
48
|
+
export declare function bindModal(triggerId: string, backdropId: string, options?: Omit<ModalOptions, "backdrop">): void;
|
|
49
|
+
/**
|
|
50
|
+
* Show a self-contained confirm modal and return a Promise that resolves to
|
|
51
|
+
* `true` (accept) or `false` (reject / dismiss).
|
|
52
|
+
*
|
|
53
|
+
* @example
|
|
54
|
+
* const ok = await confirmModal({ title: "Delete file?", variant: "danger" });
|
|
55
|
+
* if (ok) deleteFile();
|
|
56
|
+
*/
|
|
57
|
+
export declare function confirmModal(options: ConfirmOptions): Promise<boolean>;
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
export interface NavigationOptions {
|
|
2
|
+
/** Scope queries to this element. Defaults to document. */
|
|
3
|
+
root?: ParentNode;
|
|
4
|
+
/** Called when a nav option is activated (clicked). */
|
|
5
|
+
onSelect?: (id: string) => void;
|
|
6
|
+
}
|
|
7
|
+
export interface NavigationHandle {
|
|
8
|
+
openItem: (item: HTMLElement) => void;
|
|
9
|
+
closeItem: (item: HTMLElement) => void;
|
|
10
|
+
closeAll: () => void;
|
|
11
|
+
}
|
|
12
|
+
/**
|
|
13
|
+
* Bind interactive behaviour to a `.nav-bar` element.
|
|
14
|
+
*
|
|
15
|
+
* Expected markup structure:
|
|
16
|
+
*
|
|
17
|
+
* <nav class="nav-bar">
|
|
18
|
+
* <div class="nav-item">
|
|
19
|
+
* <button class="nav-trigger">File <i data-lucide="chevron-down"></i></button>
|
|
20
|
+
* <div class="nav-dropdown">
|
|
21
|
+
* <button class="nav-option" data-nav-id="new">New</button>
|
|
22
|
+
* <div class="nav-divider"></div>
|
|
23
|
+
* <div class="nav-option nav-option--has-sub">
|
|
24
|
+
* Export <i class="nav-option-arrow" data-lucide="chevron-right"></i>
|
|
25
|
+
* <div class="nav-submenu">
|
|
26
|
+
* <button class="nav-option" data-nav-id="export-png">PNG</button>
|
|
27
|
+
* </div>
|
|
28
|
+
* </div>
|
|
29
|
+
* </div>
|
|
30
|
+
* </div>
|
|
31
|
+
* </nav>
|
|
32
|
+
*/
|
|
33
|
+
export declare function bindNavigation(options?: NavigationOptions): NavigationHandle;
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
export interface RangeOptions {
|
|
2
|
+
/** The `.range-slider` container element. */
|
|
3
|
+
el: HTMLElement;
|
|
4
|
+
/** Minimum value. Default 0. */
|
|
5
|
+
min?: number;
|
|
6
|
+
/** Maximum value. Default 100. */
|
|
7
|
+
max?: number;
|
|
8
|
+
/** Step size. Default 1. */
|
|
9
|
+
step?: number;
|
|
10
|
+
/** Initial [lo, hi] values. Defaults to [min, max]. */
|
|
11
|
+
value?: [number, number];
|
|
12
|
+
/**
|
|
13
|
+
* Invert the fill: highlights the area outside the two thumbs (< lo and > hi)
|
|
14
|
+
* rather than between them. Requires a `.range-fill-end` sibling in the markup.
|
|
15
|
+
*/
|
|
16
|
+
inverted?: boolean;
|
|
17
|
+
/** Called whenever either thumb changes value. */
|
|
18
|
+
onChange?: (lo: number, hi: number) => void;
|
|
19
|
+
}
|
|
20
|
+
export interface RangeHandle {
|
|
21
|
+
/** Programmatically set both thumb positions. */
|
|
22
|
+
setValue(lo: number, hi: number): void;
|
|
23
|
+
/** Read current [lo, hi] values. */
|
|
24
|
+
getValue(): [number, number];
|
|
25
|
+
/** Remove all event listeners. */
|
|
26
|
+
destroy(): void;
|
|
27
|
+
}
|
|
28
|
+
export declare function bindRange(options: RangeOptions): RangeHandle;
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
export interface SearchOptions {
|
|
2
|
+
/** The text input element to attach behaviour to. */
|
|
3
|
+
input: HTMLInputElement;
|
|
4
|
+
/**
|
|
5
|
+
* Called (debounced) whenever the query changes.
|
|
6
|
+
* Use this to fetch/compute suggestions, then call handle.setSuggestions().
|
|
7
|
+
*/
|
|
8
|
+
onSearch?: (query: string) => void;
|
|
9
|
+
/**
|
|
10
|
+
* Called when the user selects a suggestion (click or keyboard Enter).
|
|
11
|
+
* The input value is already set to the selected string before this fires.
|
|
12
|
+
*/
|
|
13
|
+
onSelect?: (value: string) => void;
|
|
14
|
+
/** Debounce delay in ms before onSearch fires. Default 200. */
|
|
15
|
+
debounce?: number;
|
|
16
|
+
/** Minimum characters before onSearch fires. Default 0. */
|
|
17
|
+
minChars?: number;
|
|
18
|
+
}
|
|
19
|
+
export interface SearchHandle {
|
|
20
|
+
/**
|
|
21
|
+
* Populate the suggestions dropdown.
|
|
22
|
+
* Pass an empty array to hide the dropdown.
|
|
23
|
+
* Call this from your onSearch callback once your data is ready.
|
|
24
|
+
*/
|
|
25
|
+
setSuggestions(items: string[]): void;
|
|
26
|
+
/** Clear suggestions and hide the dropdown. */
|
|
27
|
+
clearSuggestions(): void;
|
|
28
|
+
/** Remove all event listeners. */
|
|
29
|
+
destroy(): void;
|
|
30
|
+
}
|
|
31
|
+
export declare function bindSearch(options: SearchOptions): SearchHandle;
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
export interface SplitPaneOptions {
|
|
2
|
+
/** The grid workspace element. */
|
|
3
|
+
workspace: HTMLElement;
|
|
4
|
+
/** The resizer element for the left split. */
|
|
5
|
+
leftResizer: HTMLElement;
|
|
6
|
+
/** The resizer element for the right split. */
|
|
7
|
+
rightResizer: HTMLElement;
|
|
8
|
+
/** CSS variable name for left panel width. Default "--left-panel-width". */
|
|
9
|
+
leftVar?: string;
|
|
10
|
+
/** CSS variable name for right panel width. Default "--right-panel-width". */
|
|
11
|
+
rightVar?: string;
|
|
12
|
+
minLeft?: number;
|
|
13
|
+
maxLeft?: number;
|
|
14
|
+
minRight?: number;
|
|
15
|
+
maxRight?: number;
|
|
16
|
+
}
|
|
17
|
+
export declare function bindSplitPaneResize(options: SplitPaneOptions): void;
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
export interface TabsOptions {
|
|
2
|
+
/** Selector for tab trigger buttons (must have data-tab-trigger attribute). */
|
|
3
|
+
triggerSelector?: string;
|
|
4
|
+
/** Selector for tab panel elements (must have data-tab-panel attribute). */
|
|
5
|
+
panelSelector?: string;
|
|
6
|
+
/** Container to scope the query. Defaults to document. */
|
|
7
|
+
root?: ParentNode;
|
|
8
|
+
/** Callback when a tab changes. */
|
|
9
|
+
onChange?: (tabId: string) => void;
|
|
10
|
+
}
|
|
11
|
+
export declare function bindTabs(options?: TabsOptions): {
|
|
12
|
+
activate: (tabId: string) => void;
|
|
13
|
+
};
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
export type ToastVariant = "success" | "error" | "info";
|
|
2
|
+
export interface ToastOptions {
|
|
3
|
+
message: string;
|
|
4
|
+
variant?: ToastVariant;
|
|
5
|
+
durationMs?: number;
|
|
6
|
+
}
|
|
7
|
+
export declare function mountToast(container: HTMLElement, options: ToastOptions): void;
|
|
8
|
+
/** Convenience: resolve toast element by id and show it. */
|
|
9
|
+
export declare function showToast(message: string, variant?: ToastVariant, durationMs?: number, toastId?: string): void;
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
import { IconNode } from 'lucide';
|
|
2
|
+
export declare const ICON_SET: Record<string, IconNode>;
|
|
3
|
+
/**
|
|
4
|
+
* Replace all `<i data-lucide="icon-name">` elements in the document with
|
|
5
|
+
* inline SVG. Call this once after the DOM is ready, and again after any
|
|
6
|
+
* dynamically injected HTML that contains icon placeholders.
|
|
7
|
+
*
|
|
8
|
+
* Icon names use kebab-case (e.g. "chevron-left", "sliders-horizontal").
|
|
9
|
+
*/
|
|
10
|
+
export declare function applyIcons(): void;
|
|
11
|
+
/**
|
|
12
|
+
* Create a single lucide icon as an SVGElement by kebab-case name.
|
|
13
|
+
* Useful when building HTML programmatically in TypeScript.
|
|
14
|
+
*
|
|
15
|
+
* @example
|
|
16
|
+
* const svg = createIcon("search");
|
|
17
|
+
* if (svg) btn.prepend(svg);
|
|
18
|
+
*/
|
|
19
|
+
export declare function createIcon(name: string): SVGSVGElement | null;
|
|
20
|
+
export { type IconNode };
|
package/dist/index.cjs
ADDED
|
@@ -0,0 +1,5 @@
|
|
|
1
|
+
"use strict";Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});const V=require("lucide"),G=require("@tauri-apps/api/window");function X(e){const t=Object.create(null,{[Symbol.toStringTag]:{value:"Module"}});if(e){for(const o in e)if(o!=="default"){const l=Object.getOwnPropertyDescriptor(e,o);Object.defineProperty(t,o,l.get?l:{enumerable:!0,get:()=>e[o]})}}return t.default=e,Object.freeze(t)}const Y=X(V),x=Object.fromEntries(Object.entries(Y).filter(([,e])=>Array.isArray(e)));function K(){V.createIcons({icons:x})}function U(e){const t=e.split("-").map(p=>p.charAt(0).toUpperCase()+p.slice(1)).join(""),o=x[t];if(!o)return null;const l="http://www.w3.org/2000/svg",n=document.createElementNS(l,"svg");n.setAttribute("xmlns",l),n.setAttribute("width","24"),n.setAttribute("height","24"),n.setAttribute("viewBox","0 0 24 24"),n.setAttribute("fill","none"),n.setAttribute("stroke","currentColor"),n.setAttribute("stroke-width","2"),n.setAttribute("stroke-linecap","round"),n.setAttribute("stroke-linejoin","round");for(const[p,d]of o){const g=document.createElementNS(l,p);for(const[s,i]of Object.entries(d))g.setAttribute(s,String(i));n.appendChild(g)}return n}function J(e,t=document){const o=t.getElementById(e);if(!o)throw new Error(`Missing required element: #${e}`);return o}function Q(e,t=document){return t.getElementById(e)??null}function Z(e,t=document){const o=t.querySelector(e);if(!o)throw new Error(`Missing required element: ${e}`);return o}function ee(e,t=document){return t.querySelectorAll(e)}function te(e,t,o){if(e.innerHTML="",t.length===0){const l=document.createElement("option");l.value="",l.textContent="No options available",e.appendChild(l),e.value="",e.disabled=!0;return}for(const l of t){const n=document.createElement("option");n.value=l,n.textContent=l,e.appendChild(n)}e.disabled=!1,e.value=t.includes(o)?o:t[0]}function ne(e,t){e.classList.toggle("is-disabled",t),e.querySelectorAll("input, select, button").forEach(o=>{o.disabled=t})}function oe(e={}){const{root:t=document,onSelect:o}=e,l=Array.from(t.querySelectorAll(".nav-item"));let n=null;function p(s){n&&n!==s&&d(n);const i=s.querySelector(".nav-trigger"),r=s.querySelector(".nav-dropdown");!i||!r||(i.classList.add("is-open"),r.classList.add("is-open"),n=s)}function d(s){var r;(r=s.querySelector(".nav-trigger"))==null||r.classList.remove("is-open");const i=s.querySelector(".nav-dropdown");i==null||i.classList.remove("is-open"),i==null||i.querySelectorAll(".nav-option--has-sub.is-sub-open").forEach(a=>a.classList.remove("is-sub-open")),n===s&&(n=null)}function g(){l.forEach(d)}return l.forEach(s=>{const i=s.querySelector(".nav-trigger"),r=s.querySelector(".nav-dropdown");i==null||i.addEventListener("click",a=>{a.stopPropagation(),n===s?d(s):p(s)}),i==null||i.addEventListener("mouseenter",()=>{n&&n!==s&&p(s)}),r==null||r.querySelectorAll(".nav-option--has-sub").forEach(a=>{a.addEventListener("mouseenter",()=>{r.querySelectorAll(".nav-option--has-sub.is-sub-open").forEach(f=>{f!==a&&f.classList.remove("is-sub-open")}),a.classList.add("is-sub-open")});const u=a.querySelector(".nav-submenu");u==null||u.addEventListener("mouseleave",f=>{const c=f.relatedTarget;a.contains(c)||a.classList.remove("is-sub-open")})}),r==null||r.querySelectorAll(".nav-option:not(.nav-option--has-sub)").forEach(a=>{a.addEventListener("click",u=>{if(u.stopPropagation(),a.classList.contains("nav-option--disabled"))return;const f=a.dataset.navId??"";o==null||o(f),g()})})}),document.addEventListener("click",g),document.addEventListener("keydown",s=>{s.key==="Escape"&&n&&(s.preventDefault(),g())}),{openItem:p,closeItem:d,closeAll:g}}let C=null;function F(e,t){const{message:o,variant:l="success",durationMs:n=3e3}=t;C&&(clearTimeout(C),C=null),e.textContent=o,e.className=`app-toast ${l}`,e.offsetHeight,e.classList.add("visible"),C=setTimeout(()=>{e.classList.remove("visible"),C=null},n)}function re(e,t="success",o=3e3,l="app-toast"){const n=document.getElementById(l);n&&F(n,{message:e,variant:t,durationMs:o})}function ae(e){var h;const{input:t,onSearch:o,onSelect:l,debounce:n=200,minChars:p=0}=e;let d=null,g=-1,s=[];const i=((h=t.closest(".search-field"))==null?void 0:h.querySelector(".search-suggestions"))??null;function r(b){if(s=b,g=-1,!i)return;if(i.innerHTML="",b.length===0){i.classList.remove("is-open");return}const w=document.createDocumentFragment();for(const M of b){const y=document.createElement("button");y.type="button",y.className="search-suggestion",y.textContent=M,y.addEventListener("mousedown",L=>{L.preventDefault(),a(M)}),w.appendChild(y)}i.appendChild(w),i.classList.add("is-open")}function a(b){t.value=b,i==null||i.classList.remove("is-open"),s=[],g=-1,l==null||l(b)}function u(b){var M;if(!i)return;const w=i.querySelectorAll(".search-suggestion");w.forEach((y,L)=>y.classList.toggle("is-active",L===b)),g=b,(M=w[b])==null||M.scrollIntoView({block:"nearest"})}function f(){d&&clearTimeout(d);const b=t.value;if(b.length<p){r([]);return}d=setTimeout(()=>o==null?void 0:o(b),n)}function c(b){if(i!=null&&i.classList.contains("is-open"))switch(b.key){case"ArrowDown":b.preventDefault(),u(Math.min(g+1,s.length-1));break;case"ArrowUp":b.preventDefault(),u(Math.max(g-1,0));break;case"Enter":g>=0&&(b.preventDefault(),a(s[g]));break;case"Escape":r([]);break}}function m(){setTimeout(()=>i==null?void 0:i.classList.remove("is-open"),150)}return t.addEventListener("input",f),t.addEventListener("keydown",c),t.addEventListener("blur",m),{setSuggestions:r,clearSuggestions:()=>r([]),destroy(){d&&clearTimeout(d),t.removeEventListener("input",f),t.removeEventListener("keydown",c),t.removeEventListener("blur",m)}}}function se(e){var R,j;const{el:t,min:o=0,max:l=100,step:n=1,inverted:p=!1,onChange:d}=e,g=t.querySelector(".range-track"),s=t.querySelector(".range-fill"),i=t.querySelector(".range-fill-end")??null,r=t.querySelector('[data-thumb="lo"]'),a=t.querySelector('[data-thumb="hi"]'),u=t.querySelector(".range-label-lo")??null,f=t.querySelector(".range-label-hi")??null;let c=((R=e.value)==null?void 0:R[0])??o,m=((j=e.value)==null?void 0:j[1])??l;function h(v){return Math.round((v-o)/n)*n+o}function b(v,E,S){return Math.max(E,Math.min(S,v))}function w(v){return(v-o)/(l-o)*100}function M(){const v=w(c),E=w(m);r.style.left=`${v}%`,a.style.left=`${E}%`,p?(s.style.left="0%",s.style.width=`${v}%`,i&&(i.style.left=`${E}%`,i.style.width=`${100-E}%`)):(s.style.left=`${v}%`,s.style.width=`${E-v}%`),r.setAttribute("aria-valuenow",String(c)),a.setAttribute("aria-valuenow",String(m)),r.setAttribute("aria-valuetext",String(c)),a.setAttribute("aria-valuetext",String(m)),u&&(u.textContent=String(c)),f&&(f.textContent=String(m))}function y(v){const E=g.getBoundingClientRect(),S=b((v-E.left)/E.width,0,1);return h(o+S*(l-o))}function L(v,E){E.preventDefault();const S=v==="lo"?r:a;S.classList.add("is-dragging"),S.setPointerCapture(E.pointerId);function q(I){const _=y(I.clientX);v==="lo"?c=b(_,o,m):m=b(_,c,l),M(),d==null||d(c,m)}function $(I){S.classList.remove("is-dragging"),S.releasePointerCapture(I.pointerId),S.removeEventListener("pointermove",q),S.removeEventListener("pointerup",$)}S.addEventListener("pointermove",q),S.addEventListener("pointerup",$)}function D(v){if(v.target.closest(".range-thumb"))return;const E=y(v.clientX),S=Math.abs(E-c),q=Math.abs(E-m);S<=q?c=b(E,o,m):m=b(E,c,l),M(),d==null||d(c,m)}function P(v){const E=v.currentTarget.dataset.thumb;let S=0;switch(v.key){case"ArrowRight":case"ArrowUp":S=+n;break;case"ArrowLeft":case"ArrowDown":S=-n;break;case"PageUp":S=+n*10;break;case"PageDown":S=-n*10;break;case"Home":E==="lo"&&(c=o,M(),d==null||d(c,m));return;case"End":E==="hi"&&(m=l,M(),d==null||d(c,m));return;default:return}v.preventDefault(),E==="lo"?c=b(h(c+S),o,m):m=b(h(m+S),c,l),M(),d==null||d(c,m)}return r.setAttribute("role","slider"),r.setAttribute("tabindex","0"),r.setAttribute("aria-label","Minimum"),r.setAttribute("aria-valuemin",String(o)),r.setAttribute("aria-valuemax",String(l)),a.setAttribute("role","slider"),a.setAttribute("tabindex","0"),a.setAttribute("aria-label","Maximum"),a.setAttribute("aria-valuemin",String(o)),a.setAttribute("aria-valuemax",String(l)),r.addEventListener("pointerdown",v=>L("lo",v)),a.addEventListener("pointerdown",v=>L("hi",v)),r.addEventListener("keydown",P),a.addEventListener("keydown",P),g.addEventListener("click",D),M(),{setValue(v,E){c=b(h(v),o,l),m=b(h(E),o,l),c>m&&([c,m]=[m,c]),M()},getValue(){return[c,m]},destroy(){r.removeEventListener("pointerdown",v=>L("lo",v)),a.removeEventListener("pointerdown",v=>L("hi",v)),r.removeEventListener("keydown",P),a.removeEventListener("keydown",P),g.removeEventListener("click",D)}}}function H(e){const{backdrop:t,closeOnBackdrop:o=!0,closeOnEscape:l=!0,onClose:n,onAccept:p,onReject:d,acceptBtnSelector:g=".modal-btn-accept",rejectBtnSelector:s=".modal-btn-reject"}=e;t.removeAttribute("hidden"),document.body.classList.add("modal-open");const i=()=>{W({backdrop:t,onClose:n}),p==null||p()},r=()=>{W({backdrop:t,onClose:n}),d==null||d()};if(t.querySelectorAll(g).forEach(a=>a.addEventListener("click",i,{once:!0})),t.querySelectorAll(s).forEach(a=>a.addEventListener("click",r,{once:!0})),o&&t.addEventListener("click",a=>{a.target===t&&r()},{once:!0}),l){const a=u=>{u.key==="Escape"&&(r(),document.removeEventListener("keydown",a))};document.addEventListener("keydown",a)}}function W(e){const{backdrop:t,onClose:o}=e;t.setAttribute("hidden",""),document.body.classList.remove("modal-open"),o==null||o()}function ie(e,t,o={}){const l=document.getElementById(e),n=document.getElementById(t);n&&(l==null||l.addEventListener("click",()=>H({backdrop:n,...o})))}const le=`<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" viewBox="0 0 24 24"
|
|
2
|
+
fill="none" stroke="currentColor" stroke-width="2"
|
|
3
|
+
stroke-linecap="round" stroke-linejoin="round">
|
|
4
|
+
<line x1="18" y1="6" x2="6" y2="18"/><line x1="6" y1="6" x2="18" y2="18"/>
|
|
5
|
+
</svg>`;function ce(e){const{title:t,message:o,acceptLabel:l="Confirm",rejectLabel:n="Cancel",variant:p="default",closeOnBackdrop:d=!0,closeOnEscape:g=!0}=e;return new Promise(s=>{const i=document.createElement("div");i.className="modal-backdrop";const r=document.createElement("div");r.className="modal-card",r.setAttribute("role","dialog"),r.setAttribute("aria-modal","true");const a=document.createElement("div");a.className="modal-header";const u=document.createElement("h3");u.textContent=t;const f=document.createElement("button");if(f.className="icon-btn modal-close-btn modal-btn-reject",f.setAttribute("aria-label","Close"),f.innerHTML=le,a.append(u,f),r.appendChild(a),o){const y=document.createElement("p");y.className="modal-body-text",y.textContent=o,r.appendChild(y)}const c=document.createElement("div");c.className="modal-footer";const m=document.createElement("button");m.className="secondary-btn modal-btn-reject",m.textContent=n;const h=document.createElement("button");h.className=`modal-btn-accept${p==="danger"?" danger":""}`,h.textContent=l,c.append(m,h),r.appendChild(c),i.appendChild(r),document.body.appendChild(i),document.body.classList.add("modal-open"),requestAnimationFrame(()=>m.focus());const b=()=>{i.remove(),document.body.classList.remove("modal-open")},w=()=>{b(),s(!0)},M=()=>{b(),s(!1)};if(h.addEventListener("click",w,{once:!0}),i.querySelectorAll(".modal-btn-reject").forEach(y=>y.addEventListener("click",M,{once:!0})),d&&i.addEventListener("click",y=>{y.target===i&&M()},{once:!0}),g){const y=L=>{L.key==="Escape"&&(M(),document.removeEventListener("keydown",y))};document.addEventListener("keydown",y)}})}function de(e={}){var i,r;const{triggerSelector:t="[data-tab-trigger]",panelSelector:o="[data-tab-panel]",root:l=document,onChange:n}=e,p=Array.from(l.querySelectorAll(t)),d=Array.from(l.querySelectorAll(o));function g(a){p.forEach(u=>{u.classList.toggle("is-active",u.dataset.tabTrigger===a)}),d.forEach(u=>{u.classList.toggle("is-active",u.dataset.tabPanel===a)}),n==null||n(a)}p.forEach(a=>{a.addEventListener("click",()=>{const u=a.dataset.tabTrigger;u&&g(u)})});const s=((i=p.find(a=>a.classList.contains("is-active")))==null?void 0:i.dataset.tabTrigger)??((r=p[0])==null?void 0:r.dataset.tabTrigger);return s&&g(s),{activate:g}}function ue(e){const{workspace:t,leftResizer:o,rightResizer:l,leftVar:n="--left-panel-width",rightVar:p="--right-panel-width",minLeft:d=160,maxLeft:g=480,minRight:s=160,maxRight:i=520}=e;let r=null,a=0,u=0;function f(){return parseInt(getComputedStyle(t).getPropertyValue(n)||"220",10)}function c(){return parseInt(getComputedStyle(t).getPropertyValue(p)||"260",10)}o.addEventListener("mousedown",m=>{r="left",a=m.clientX,u=f(),m.preventDefault()}),l.addEventListener("mousedown",m=>{r="right",a=m.clientX,u=c(),m.preventDefault()}),document.addEventListener("mousemove",m=>{if(r)if(r==="left"){const h=m.clientX-a,b=Math.min(g,Math.max(d,u+h));t.style.setProperty(n,`${b}px`)}else{const h=a-m.clientX,b=Math.min(i,Math.max(s,u+h));t.style.setProperty(p,`${b}px`)}}),document.addEventListener("mouseup",()=>{r=null})}function me(e={}){const{minimizeBtnId:t="window-minimize-btn",maximizeBtnId:o="window-maximize-btn",closeBtnId:l="window-close-btn"}=e,n=G.getCurrentWindow(),p=document.getElementById(t),d=document.getElementById(o),g=document.getElementById(l);p==null||p.addEventListener("click",async()=>{try{await n.minimize()}catch(s){console.error("Failed to minimize window:",s)}}),d&&(d.addEventListener("click",async()=>{try{const s=await n.isMaximized();s?await n.unmaximize():await n.maximize(),O(d,!s)}catch(s){console.error("Failed to toggle maximize:",s)}}),n.isMaximized().then(s=>O(d,s)).catch(()=>{}),n.onResized(async()=>{try{const s=await n.isMaximized();O(d,s)}catch{}})),g==null||g.addEventListener("click",async()=>{try{await n.close()}catch(s){console.error("Failed to close window:",s)}})}function O(e,t){e.dataset.maximized=String(t);const o=e.querySelector("svg");if(!o)return;const l=t?[["polyline","points","4 14 10 14 10 20"],["polyline","points","20 10 14 10 14 4"],["line","x1,y1,x2,y2","10,20,3,13"],["line","x1,y1,x2,y2","21,3,14,10"]]:[["polyline","points","15 3 21 3 21 9"],["polyline","points","9 21 3 21 3 15"],["line","x1,y1,x2,y2","21,3,14,10"],["line","x1,y1,x2,y2","3,21,10,14"]];o.innerHTML="";const n="http://www.w3.org/2000/svg";for(const[p,d,g]of l){const s=document.createElementNS(n,p),i=d.split(","),r=g.split(",");i.forEach((a,u)=>s.setAttribute(a,r[u]??"")),o.appendChild(s)}}function fe(){window.addEventListener("contextmenu",e=>{e.preventDefault()}),window.addEventListener("keydown",e=>{(e.key==="ContextMenu"||e.shiftKey&&e.key==="F10")&&e.preventDefault()})}const T=["classic","bars","pulse","bloom","fan"],B=["aurora","ember","glacier","sunset","monochrome"],A={aurora:{horizontalStart:"rgba(108, 99, 255, 0.3)",horizontalMid:"rgba(74, 222, 128, 0.95)",horizontalEnd:"rgba(108, 99, 255, 0.3)",verticalTop:"rgba(167, 139, 250, 0.7)",verticalMid:"rgba(74, 222, 128, 0.95)",verticalBottom:"rgba(34, 211, 238, 0.62)",glow:"rgba(74, 222, 128, 0.45)",progressStart:"rgba(251, 191, 36, 0.95)",progressEnd:"rgba(248, 113, 113, 0.9)",label:"Aurora"},ember:{horizontalStart:"rgba(251, 146, 60, 0.34)",horizontalMid:"rgba(248, 113, 113, 0.98)",horizontalEnd:"rgba(245, 158, 11, 0.34)",verticalTop:"rgba(253, 186, 116, 0.78)",verticalMid:"rgba(248, 113, 113, 0.94)",verticalBottom:"rgba(239, 68, 68, 0.66)",glow:"rgba(248, 113, 113, 0.42)",progressStart:"rgba(253, 224, 71, 0.96)",progressEnd:"rgba(239, 68, 68, 0.9)",label:"Ember"},glacier:{horizontalStart:"rgba(96, 165, 250, 0.3)",horizontalMid:"rgba(125, 211, 252, 0.95)",horizontalEnd:"rgba(45, 212, 191, 0.3)",verticalTop:"rgba(191, 219, 254, 0.76)",verticalMid:"rgba(125, 211, 252, 0.92)",verticalBottom:"rgba(45, 212, 191, 0.62)",glow:"rgba(96, 165, 250, 0.38)",progressStart:"rgba(165, 243, 252, 0.95)",progressEnd:"rgba(96, 165, 250, 0.88)",label:"Glacier"},sunset:{horizontalStart:"rgba(244, 114, 182, 0.32)",horizontalMid:"rgba(251, 191, 36, 0.96)",horizontalEnd:"rgba(249, 115, 22, 0.34)",verticalTop:"rgba(251, 207, 232, 0.76)",verticalMid:"rgba(251, 191, 36, 0.93)",verticalBottom:"rgba(249, 115, 22, 0.66)",glow:"rgba(251, 191, 36, 0.4)",progressStart:"rgba(253, 224, 71, 0.96)",progressEnd:"rgba(236, 72, 153, 0.9)",label:"Sunset"},monochrome:{horizontalStart:"rgba(148, 163, 184, 0.25)",horizontalMid:"rgba(241, 245, 249, 0.95)",horizontalEnd:"rgba(148, 163, 184, 0.25)",verticalTop:"rgba(226, 232, 240, 0.68)",verticalMid:"rgba(241, 245, 249, 0.92)",verticalBottom:"rgba(148, 163, 184, 0.55)",glow:"rgba(226, 232, 240, 0.26)",progressStart:"rgba(248, 250, 252, 0.92)",progressEnd:"rgba(148, 163, 184, 0.82)",label:"Monochrome"}};function ge(e){return typeof e=="string"&&T.includes(e)}function pe(e){return typeof e=="string"&&B.includes(e)}function be(e){const t=T.indexOf(e);return T[(t+1)%T.length]}function ve(e){const t=B.indexOf(e);return B[(t+1)%B.length]}function he(e){return{classic:"Classic",bars:"Bars",pulse:"Pulse",bloom:"Bloom",fan:"Fan"}[e]}function ye(e){return A[e].label}function k(e,t){const o=e.match(/^rgba\((.+?),\s*([0-9.]+)\)$/);return o?`rgba(${o[1]}, ${Number(o[2])*t})`:e}function z(e,t,o,l=1){const n=e.createLinearGradient(0,0,t,0);return n.addColorStop(0,k(o.horizontalStart,l)),n.addColorStop(.5,k(o.horizontalMid,l)),n.addColorStop(1,k(o.horizontalEnd,l)),n}function N(e,t,o,l=1){const n=e.createLinearGradient(0,0,0,t);return n.addColorStop(0,k(o.verticalTop,l)),n.addColorStop(.45,k(o.verticalMid,l)),n.addColorStop(1,k(o.verticalBottom,l)),n}function Ee({ctx:e,width:t,height:o,amplitude:l,phase:n,colorScheme:p}){const d=A[p],g=o/2;e.lineWidth=2,e.strokeStyle=z(e,t,d),e.shadowColor=d.glow,e.shadowBlur=12,e.beginPath();for(let s=0;s<=t;s+=2){const i=s/Math.max(t,1),r=Math.sin(i*Math.PI),a=g+Math.sin(i*10+n)*l*r+Math.sin(i*22+n*1.8)*l*.16;s===0?e.moveTo(s,a):e.lineTo(s,a)}e.stroke(),e.shadowBlur=0}function Se({ctx:e,width:t,height:o,amplitude:l,phase:n,active:p,colorScheme:d}){const g=A[d],s=o/2,i=6,r=3,a=Math.max(2,o*.08),u=Math.max(a+2,Math.min(o*.92,a+l*2.4));e.fillStyle=N(e,o,g,p?1:.72),e.shadowColor=k(g.glow,.84),e.shadowBlur=p?10:0;for(let f=0;f<=t;f+=i){const c=f/Math.max(t,1),m=Math.sin(c*18-n*1.9),h=Math.sin(c*8+n*1.15),b=Math.max(0,m*.72+h*.28),w=p?.2+b*.8:0,M=a+(u-a)*w,y=s-M/2;e.fillRect(f,y,r,M)}e.shadowBlur=0}function Me({ctx:e,width:t,height:o,amplitude:l,phase:n,active:p,colorScheme:d}){const g=A[d],s=o/2,i=p?Math.max(3,l*1.25):0;e.fillStyle=N(e,o,g,.28),e.beginPath();for(let r=0;r<=t;r+=4){const a=r/Math.max(t,1),u=.32+Math.sin(a*Math.PI)*.68,f=Math.sin(a*8+n*.95)+Math.sin(a*17-n*1.6)*.35,c=s-i*u*f*.7;r===0?e.moveTo(r,c):e.lineTo(r,c)}for(let r=t;r>=0;r-=4){const a=r/Math.max(t,1),u=.32+Math.sin(a*Math.PI)*.68,f=Math.sin(a*8+n*.95)+Math.sin(a*17-n*1.6)*.35,c=s+i*u*f*.7;e.lineTo(r,c)}e.closePath(),e.fill(),e.lineWidth=1.5,e.strokeStyle=z(e,t,g),e.shadowColor=k(g.glow,.88),e.shadowBlur=p?10:0,e.beginPath();for(let r=0;r<=t;r+=3){const a=r/Math.max(t,1),u=.32+Math.sin(a*Math.PI)*.68,f=Math.sin(a*8+n*.95)+Math.sin(a*17-n*1.6)*.35,c=s+i*u*f*.45;r===0?e.moveTo(r,c):e.lineTo(r,c)}e.stroke(),e.shadowBlur=0}function we({ctx:e,width:t,height:o,amplitude:l,phase:n,active:p,colorScheme:d}){const g=A[d],s=t/2,i=o/2,r=t/2,a=24,u=p?Math.max(4,l*1.4):0;e.lineWidth=1.8,e.strokeStyle=z(e,t,g),e.shadowColor=k(g.glow,.9),e.shadowBlur=p?12:0;for(let f=0;f<a;f+=1){const c=(f+1)/a,m=c*r,h=Math.pow(1-c,.45),b=Math.sin(n*1.15-c*12)*.7+Math.sin(n*.65-c*6.5)*.3,w=1+u*h*Math.max(.15,b+.45);e.beginPath(),e.moveTo(s-m,i-w),e.lineTo(s-m,i+w),e.moveTo(s+m,i-w),e.lineTo(s+m,i+w),e.stroke()}e.shadowBlur=0}function Le({ctx:e,width:t,height:o,amplitude:l,phase:n,active:p,colorScheme:d}){const g=A[d],s=t/2,i=o/2,r=t/2,a=p?Math.max(4,l*1.15):0;e.fillStyle=N(e,o,g,.22),e.strokeStyle=z(e,t,g),e.lineWidth=1.6,e.shadowColor=k(g.glow,.85),e.shadowBlur=p?10:0,e.beginPath(),e.moveTo(s,i);for(let u=0;u<=r;u+=3){const f=u/Math.max(r,1),c=Math.sin(f*Math.PI*.95),m=Math.sin(n*1.25+f*10)+Math.sin(n*.82+f*18)*.24,h=i-a*c*m*.58;e.lineTo(s+u,h)}for(let u=r;u>=0;u-=3){const f=u/Math.max(r,1),c=Math.sin(f*Math.PI*.95),m=Math.sin(n*1.25+f*10)+Math.sin(n*.82+f*18)*.24,h=i+a*c*m*.58;e.lineTo(s+u,h)}e.closePath(),e.fill();for(const u of[1,-1]){e.beginPath(),e.moveTo(s,i);for(let f=0;f<=r;f+=3){const c=f/Math.max(r,1),m=Math.sin(c*Math.PI*.95),h=Math.sin(n*1.25+c*10)+Math.sin(n*.82+c*18)*.24,b=i-a*m*h*.58;e.lineTo(s+u*f,b)}e.stroke(),e.beginPath(),e.moveTo(s,i);for(let f=0;f<=r;f+=3){const c=f/Math.max(r,1),m=Math.sin(c*Math.PI*.95),h=Math.sin(n*1.25+c*10)+Math.sin(n*.82+c*18)*.24,b=i+a*m*h*.58;e.lineTo(s+u*f,b)}e.stroke()}e.shadowBlur=0}function ke(e,t){({classic:Ee,bars:Se,pulse:Me,bloom:we,fan:Le})[e](t)}function Ae(e,t,o){const l=A[o],n=e.createLinearGradient(0,0,0,t);return n.addColorStop(0,l.progressStart),n.addColorStop(1,l.progressEnd),n}exports.ICON_SET=x;exports.WAVEFORM_COLOR_SCHEMES=B;exports.WAVEFORM_STYLES=T;exports.applyIcons=K;exports.bindModal=ie;exports.bindNavigation=oe;exports.bindRange=se;exports.bindSearch=ae;exports.bindSplitPaneResize=ue;exports.bindTabs=de;exports.byId=J;exports.byIdOptional=Q;exports.closeModal=W;exports.confirmModal=ce;exports.createIcon=U;exports.createWaveProgressGradient=Ae;exports.cycleWaveformColorScheme=ve;exports.cycleWaveformStyle=be;exports.drawWaveform=ke;exports.getWaveformColorSchemeLabel=ye;exports.getWaveformStyleLabel=he;exports.isWaveformColorScheme=pe;exports.isWaveformStyle=ge;exports.mountToast=F;exports.openModal=H;exports.populateSelectOptions=te;exports.qs=Z;exports.qsAll=ee;exports.setGroupDisabled=ne;exports.setupContextMenuGuard=fe;exports.setupWindowControls=me;exports.showToast=re;
|
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
export { applyIcons, createIcon, ICON_SET } from './icons/index';
|
|
2
|
+
export type { IconNode } from './icons/index';
|
|
3
|
+
export { byId, byIdOptional, qs, qsAll, populateSelectOptions, setGroupDisabled } from './headless/dom';
|
|
4
|
+
export { bindNavigation } from './headless/navigation';
|
|
5
|
+
export type { NavigationOptions, NavigationHandle } from './headless/navigation';
|
|
6
|
+
export { mountToast, showToast } from './headless/toast';
|
|
7
|
+
export type { ToastOptions, ToastVariant } from './headless/toast';
|
|
8
|
+
export { bindSearch } from './headless/search';
|
|
9
|
+
export type { SearchOptions, SearchHandle } from './headless/search';
|
|
10
|
+
export { bindRange } from './headless/range';
|
|
11
|
+
export type { RangeOptions, RangeHandle } from './headless/range';
|
|
12
|
+
export { openModal, closeModal, bindModal, confirmModal } from './headless/modal';
|
|
13
|
+
export type { ModalOptions, ConfirmOptions } from './headless/modal';
|
|
14
|
+
export { bindTabs } from './headless/tabs';
|
|
15
|
+
export type { TabsOptions } from './headless/tabs';
|
|
16
|
+
export { bindSplitPaneResize } from './headless/split-pane';
|
|
17
|
+
export type { SplitPaneOptions } from './headless/split-pane';
|
|
18
|
+
export { setupWindowControls, setupContextMenuGuard } from './platform/tauri-window';
|
|
19
|
+
export type { WindowControlOptions } from './platform/tauri-window';
|
|
20
|
+
export { WAVEFORM_STYLES, WAVEFORM_COLOR_SCHEMES, isWaveformStyle, isWaveformColorScheme, cycleWaveformStyle, cycleWaveformColorScheme, getWaveformStyleLabel, getWaveformColorSchemeLabel, drawWaveform, createWaveProgressGradient, } from './waveform/waveform';
|
|
21
|
+
export type { WaveformStyle, WaveformColorScheme, DrawWaveformOptions } from './waveform/waveform';
|