slexkit 0.2.0 → 0.3.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/CHANGELOG.md +52 -0
- package/LICENSE +21 -21
- package/dist/ai/llms-authoring.txt +2 -0
- package/dist/ai/llms-capabilities.txt +126 -0
- package/dist/ai/llms-components.txt +27 -6
- package/dist/ai/llms-full.txt +1729 -4
- package/dist/ai/llms-runtime.txt +7 -1
- package/dist/ai/llms.txt +22 -1
- package/dist/ai/slexkit-ai-manifest.json +674 -23
- package/dist/base.css +359 -359
- package/dist/chunks/{accordion-cfjyxw93.js → button-53ccjq5p.js} +11 -11
- package/dist/chunks/{accordion-nw12ytps.js → button-cr1fhsa7.js} +48 -2
- package/dist/chunks/{accordion-5f0nvjjm.js → button-dsftwzvg.js} +4 -3
- package/dist/chunks/{accordion-hzyrngd6.js → button-faf563xf.js} +2 -2
- package/dist/chunks/{accordion-ehnhpeca.js → button-jxv4c65t.js} +2 -2
- package/dist/chunks/{accordion-cw5r75jm.js → button-xv2dz7vn.js} +1 -1
- package/dist/chunks/{accordion-830dw78f.js → button-z5yv24ks.js} +2 -2
- package/dist/components/accordion.js +2 -2
- package/dist/components/badge.js +2 -2
- package/dist/components/button.css +101 -101
- package/dist/components/button.js +3 -3
- package/dist/components/callout.js +4 -4
- package/dist/components/card.js +2 -2
- package/dist/components/checkbox.js +2 -2
- package/dist/components/choice.css +151 -151
- package/dist/components/code-block.js +2 -2
- package/dist/components/collapsible.js +2 -2
- package/dist/components/column.js +1 -1
- package/dist/components/content.css +273 -250
- package/dist/components/divider.js +2 -2
- package/dist/components/grid.js +1 -1
- package/dist/components/index.js +13945 -26
- package/dist/components/input.css +777 -777
- package/dist/components/input.js +8 -8
- package/dist/components/link.js +2 -2
- package/dist/components/progress.js +2 -2
- package/dist/components/radio-group.js +2 -2
- package/dist/components/row.js +1 -1
- package/dist/components/section.js +2 -2
- package/dist/components/select.css +178 -178
- package/dist/components/select.js +3 -3
- package/dist/components/slider.css +116 -116
- package/dist/components/slider.js +2 -2
- package/dist/components/specs.js +32 -0
- package/dist/components/stat.js +2 -2
- package/dist/components/submit.css +8 -8
- package/dist/components/submit.js +1 -1
- package/dist/components/switch.css +105 -105
- package/dist/components/switch.js +3 -3
- package/dist/components/table.js +4 -4
- package/dist/components/tabs.css +95 -95
- package/dist/components/tabs.js +4 -4
- package/dist/components/text-input.css +23 -23
- package/dist/components/text.js +1 -1
- package/dist/components/toast.js +4 -4
- package/dist/components/tooling.js +73 -8
- package/dist/runtime.cjs +1590 -14
- package/dist/runtime.js +1589 -13
- package/dist/slexkit.cjs +28254 -13848
- package/dist/slexkit.css +1538 -1515
- package/dist/slexkit.js +28253 -13847
- package/dist/tooling.js +117 -11
- package/dist/types/components/svelte/helpers.d.ts +8 -1
- package/dist/types/engine/capabilities.d.ts +54 -0
- package/dist/types/engine/index.d.ts +6 -0
- package/dist/types/engine/secure-runtime.d.ts +9 -1
- package/dist/types/engine/stdlib.d.ts +30 -0
- package/dist/types/engine/types.d.ts +1 -0
- package/dist/types/engine/validation.d.ts +28 -0
- package/dist/types/index.d.ts +6 -3
- package/dist/types/runtime.d.ts +6 -3
- package/dist/types/version.d.ts +2 -2
- package/dist/umd/slexkit.tooling.umd.js +45016 -44626
- package/dist/umd/slexkit.umd.js +28255 -13849
- package/package.json +3 -2
- package/src/components/svelte/content/Formula.svelte +27 -0
- package/src/components/svelte/content/Table.svelte +1 -1
- package/src/components/svelte/helpers.ts +56 -1
- package/src/components/svelte/input/Input.svelte +7 -7
- package/src/components/svelte/input/Select.svelte +2 -2
- package/src/components/svelte/input/Switch.svelte +1 -1
- package/src/components/svelte/input/Tabs.svelte +7 -7
- package/src/components/svelte/tooling/PlaygroundMarkdown.svelte +84 -2
- package/src/styles/components/button.css +101 -101
- package/src/styles/components/choice.css +152 -152
- package/src/styles/components/select.css +178 -178
- package/src/styles/components/slider.css +116 -116
- package/src/styles/components/submit.css +8 -8
- package/src/styles/components/switch.css +105 -105
- package/src/styles/components/tabs.css +95 -95
- package/src/styles/components/text-input.css +23 -23
- package/src/styles/content.css +274 -251
- package/src/styles/input.css +8 -8
- package/src/styles/layout.css +360 -360
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "slexkit",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.3.0",
|
|
4
4
|
"description": "Zero-build, Markdown-friendly reactive UI runtime for AI output.",
|
|
5
5
|
"author": "SlexKit contributors",
|
|
6
6
|
"type": "module",
|
|
@@ -16,7 +16,7 @@
|
|
|
16
16
|
"module": "./dist/slexkit.js",
|
|
17
17
|
"types": "./dist/types/index.d.ts",
|
|
18
18
|
"bin": {
|
|
19
|
-
"slex": "
|
|
19
|
+
"slex": "scripts/cli.mjs"
|
|
20
20
|
},
|
|
21
21
|
"workspaces": [
|
|
22
22
|
"packages/*"
|
|
@@ -92,6 +92,7 @@
|
|
|
92
92
|
"copy-runtime": "node scripts/cli.mjs copy-runtime",
|
|
93
93
|
"preview": "bun run site/server.ts",
|
|
94
94
|
"smoke:release": "node scripts/release-smoke.mjs",
|
|
95
|
+
"smoke:registry": "node scripts/registry-smoke.mjs",
|
|
95
96
|
"test": "bun test --conditions browser --isolate --preload ./tests/setup.ts tests packages",
|
|
96
97
|
"test:watch": "bun test --conditions browser --isolate --watch --preload ./tests/setup.ts tests packages",
|
|
97
98
|
"lint": "eslint src/",
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
<script lang="ts">
|
|
2
|
+
import katex from "katex";
|
|
3
|
+
import { bindPropStore } from "../bindProps";
|
|
4
|
+
import { bool, text } from "../helpers";
|
|
5
|
+
import type { PropValues, SvelteComponentProps } from "../types";
|
|
6
|
+
|
|
7
|
+
let { props }: SvelteComponentProps = $props();
|
|
8
|
+
let p = $state<PropValues>({});
|
|
9
|
+
$effect(() => bindPropStore(props, (next) => (p = next)));
|
|
10
|
+
|
|
11
|
+
const tex = $derived(text(p.tex ?? p.formula ?? p.value));
|
|
12
|
+
const displayMode = $derived(p.displayMode === undefined && p.display === undefined && p.block === undefined
|
|
13
|
+
? true
|
|
14
|
+
: bool(p.displayMode ?? p.display ?? p.block));
|
|
15
|
+
const rendered = $derived(renderFormula(tex, displayMode));
|
|
16
|
+
|
|
17
|
+
function renderFormula(source: string, display: boolean): string {
|
|
18
|
+
return katex.renderToString(source || "\\,", {
|
|
19
|
+
displayMode: display,
|
|
20
|
+
throwOnError: false,
|
|
21
|
+
strict: "ignore",
|
|
22
|
+
output: "htmlAndMathml",
|
|
23
|
+
});
|
|
24
|
+
}
|
|
25
|
+
</script>
|
|
26
|
+
|
|
27
|
+
<div class="slex-formula" data-display={displayMode ? "block" : "inline"}>{@html rendered}</div>
|
|
@@ -31,7 +31,7 @@
|
|
|
31
31
|
{#each rows(p.rows ?? p.items) as row}
|
|
32
32
|
<tr>
|
|
33
33
|
{#if readColumns(p.columns).length}
|
|
34
|
-
{#each readColumns(p.columns) as column}<td>{readCell(row, column)}</td>{/each}
|
|
34
|
+
{#each readColumns(p.columns) as column, index}<td>{readCell(row, column, index)}</td>{/each}
|
|
35
35
|
{:else if Array.isArray(row)}
|
|
36
36
|
{#each row as cell}<td>{text(cell)}</td>{/each}
|
|
37
37
|
{:else}
|
|
@@ -76,7 +76,8 @@ export function readColumnLabel(column: unknown, fallback: string): string {
|
|
|
76
76
|
return text(column, fallback);
|
|
77
77
|
}
|
|
78
78
|
|
|
79
|
-
export function readCell(row: unknown, column: string): string {
|
|
79
|
+
export function readCell(row: unknown, column: string, index?: number): string {
|
|
80
|
+
if (Array.isArray(row)) return text(typeof index === "number" ? row[index] : undefined);
|
|
80
81
|
if (row && typeof row === "object") return text((row as Record<string, unknown>)[column]);
|
|
81
82
|
return text(row);
|
|
82
83
|
}
|
|
@@ -105,6 +106,7 @@ export function catalogGroups(value: unknown): Array<{ label: string; items: Rec
|
|
|
105
106
|
|
|
106
107
|
export function renderChildren(node: HTMLElement, ctx: RenderContext) {
|
|
107
108
|
if (ctx.children && Object.keys(ctx.children).length > 0) {
|
|
109
|
+
node.replaceChildren();
|
|
108
110
|
ctx.renderTree(ctx.children, node, ctx.forCtx);
|
|
109
111
|
}
|
|
110
112
|
return {
|
|
@@ -118,6 +120,59 @@ export function emit(ctx: RenderContext, event: string, data?: unknown): void {
|
|
|
118
120
|
ctx.emit(event, data);
|
|
119
121
|
}
|
|
120
122
|
|
|
123
|
+
export type ScheduledFrame = {
|
|
124
|
+
kind: "api" | "native" | "microtask";
|
|
125
|
+
id?: unknown;
|
|
126
|
+
canceled: boolean;
|
|
127
|
+
};
|
|
128
|
+
|
|
129
|
+
export function scheduleFrame(ctx: RenderContext, fn: (time?: number) => void): ScheduledFrame {
|
|
130
|
+
const handle: ScheduledFrame = { kind: "microtask", canceled: false };
|
|
131
|
+
const run = (time?: number) => {
|
|
132
|
+
if (!handle.canceled) fn(time);
|
|
133
|
+
};
|
|
134
|
+
const apiRaf = ctx.api?.raf;
|
|
135
|
+
if (typeof apiRaf === "function") {
|
|
136
|
+
try {
|
|
137
|
+
handle.kind = "api";
|
|
138
|
+
handle.id = apiRaf(run);
|
|
139
|
+
return handle;
|
|
140
|
+
} catch {
|
|
141
|
+
handle.kind = "microtask";
|
|
142
|
+
handle.id = undefined;
|
|
143
|
+
}
|
|
144
|
+
}
|
|
145
|
+
|
|
146
|
+
const ownerWindow = ctx.document.defaultView;
|
|
147
|
+
if (ownerWindow && typeof ownerWindow.requestAnimationFrame === "function") {
|
|
148
|
+
try {
|
|
149
|
+
handle.kind = "native";
|
|
150
|
+
handle.id = ownerWindow.requestAnimationFrame(run);
|
|
151
|
+
return handle;
|
|
152
|
+
} catch {
|
|
153
|
+
handle.kind = "microtask";
|
|
154
|
+
handle.id = undefined;
|
|
155
|
+
}
|
|
156
|
+
}
|
|
157
|
+
|
|
158
|
+
queueMicrotask(() => run());
|
|
159
|
+
return handle;
|
|
160
|
+
}
|
|
161
|
+
|
|
162
|
+
export function cancelScheduledFrame(ctx: RenderContext, handle: ScheduledFrame | undefined): void {
|
|
163
|
+
if (!handle || handle.canceled) return;
|
|
164
|
+
handle.canceled = true;
|
|
165
|
+
if (handle.kind === "api" && typeof ctx.api?.cancelRaf === "function") {
|
|
166
|
+
try {
|
|
167
|
+
ctx.api.cancelRaf(handle.id);
|
|
168
|
+
} catch {
|
|
169
|
+
// The runtime may already be disposed; cancellation is best effort.
|
|
170
|
+
}
|
|
171
|
+
} else if (handle.kind === "native" && typeof handle.id === "number") {
|
|
172
|
+
ctx.document.defaultView?.cancelAnimationFrame(handle.id);
|
|
173
|
+
}
|
|
174
|
+
}
|
|
175
|
+
|
|
121
176
|
function formatScriptKey(key: string): string {
|
|
122
177
|
return /^[A-Za-z_$][\w$]*$/.test(key) ? key : JSON.stringify(key);
|
|
123
178
|
}
|
|
@@ -176,13 +176,6 @@
|
|
|
176
176
|
{/if}
|
|
177
177
|
{#if controls}
|
|
178
178
|
<span class="slex-input-controls">
|
|
179
|
-
<button
|
|
180
|
-
class="slex-input-step"
|
|
181
|
-
type="button"
|
|
182
|
-
aria-label={`Decrease ${controlLabel}`}
|
|
183
|
-
disabled={decrementDisabled}
|
|
184
|
-
onclick={() => stepBy(-1)}
|
|
185
|
-
>-</button>
|
|
186
179
|
<button
|
|
187
180
|
class="slex-input-step"
|
|
188
181
|
type="button"
|
|
@@ -190,6 +183,13 @@
|
|
|
190
183
|
disabled={incrementDisabled}
|
|
191
184
|
onclick={() => stepBy(1)}
|
|
192
185
|
>+</button>
|
|
186
|
+
<button
|
|
187
|
+
class="slex-input-step"
|
|
188
|
+
type="button"
|
|
189
|
+
aria-label={`Decrease ${controlLabel}`}
|
|
190
|
+
disabled={decrementDisabled}
|
|
191
|
+
onclick={() => stepBy(-1)}
|
|
192
|
+
>-</button>
|
|
193
193
|
</span>
|
|
194
194
|
{/if}
|
|
195
195
|
</div>
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
<script lang="ts">
|
|
2
2
|
import { onMount } from "svelte";
|
|
3
3
|
import { bindPropStore } from "../bindProps";
|
|
4
|
-
import { emit, label, list, text } from "../helpers";
|
|
4
|
+
import { emit, label, list, scheduleFrame, text } from "../helpers";
|
|
5
5
|
import InlineIcon from "../InlineIcon.svelte";
|
|
6
6
|
import type { PropValues, SvelteComponentProps } from "../types";
|
|
7
7
|
|
|
@@ -97,7 +97,7 @@
|
|
|
97
97
|
function close(focusTrigger = true): void {
|
|
98
98
|
open = false;
|
|
99
99
|
activeIndex = selectedIndex();
|
|
100
|
-
if (focusTrigger)
|
|
100
|
+
if (focusTrigger) scheduleFrame(ctx, () => triggerEl?.focus());
|
|
101
101
|
}
|
|
102
102
|
|
|
103
103
|
function toggle(): void {
|
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
import FlowbiteTabs from "../../../../node_modules/flowbite-svelte/dist/tabs/Tabs.svelte";
|
|
3
3
|
import FlowbiteTabItem from "../../../../node_modules/flowbite-svelte/dist/tabs/TabItem.svelte";
|
|
4
4
|
import { bindPropStore } from "../bindProps";
|
|
5
|
-
import { emit, list, text } from "../helpers";
|
|
5
|
+
import { cancelScheduledFrame, emit, list, scheduleFrame, text, type ScheduledFrame } from "../helpers";
|
|
6
6
|
import InlineIcon from "../InlineIcon.svelte";
|
|
7
7
|
import type { PropValues, SvelteComponentProps } from "../types";
|
|
8
8
|
|
|
@@ -55,14 +55,14 @@
|
|
|
55
55
|
}
|
|
56
56
|
|
|
57
57
|
function annotateTabs(node: HTMLElement) {
|
|
58
|
-
let
|
|
58
|
+
let frame: ScheduledFrame | undefined;
|
|
59
59
|
let resizeObserver: ResizeObserver | undefined;
|
|
60
60
|
let indicatorReady = false;
|
|
61
61
|
|
|
62
62
|
function scheduleIndicatorUpdate(list: HTMLElement, selectedTrigger: HTMLElement | undefined) {
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
63
|
+
cancelScheduledFrame(ctx, frame);
|
|
64
|
+
frame = scheduleFrame(ctx, () => {
|
|
65
|
+
frame = undefined;
|
|
66
66
|
if (!selectedTrigger) {
|
|
67
67
|
list.style.setProperty("--slex-tabs-indicator-opacity", "0");
|
|
68
68
|
return;
|
|
@@ -96,7 +96,7 @@
|
|
|
96
96
|
list.style.setProperty("--slex-tabs-indicator-opacity", "1");
|
|
97
97
|
if (!indicatorReady) {
|
|
98
98
|
indicatorReady = true;
|
|
99
|
-
|
|
99
|
+
scheduleFrame(ctx, () => {
|
|
100
100
|
list.dataset.indicatorReady = "true";
|
|
101
101
|
});
|
|
102
102
|
}
|
|
@@ -137,7 +137,7 @@
|
|
|
137
137
|
apply();
|
|
138
138
|
},
|
|
139
139
|
destroy() {
|
|
140
|
-
|
|
140
|
+
cancelScheduledFrame(ctx, frame);
|
|
141
141
|
resizeObserver?.disconnect();
|
|
142
142
|
},
|
|
143
143
|
};
|
|
@@ -15,10 +15,92 @@
|
|
|
15
15
|
inlineKatex: KatexRenderer,
|
|
16
16
|
blockKatex: KatexRenderer,
|
|
17
17
|
};
|
|
18
|
+
const options = { headerIds: false };
|
|
19
|
+
|
|
20
|
+
function stripFrontmatter(value: string) {
|
|
21
|
+
const raw = String(value ?? "").replace(/^\uFEFF/, "").replace(/\r\n/g, "\n");
|
|
22
|
+
if (!raw.startsWith("---")) return raw;
|
|
23
|
+
|
|
24
|
+
const end = raw.indexOf("\n---", 3);
|
|
25
|
+
if (end === -1) return raw;
|
|
26
|
+
|
|
27
|
+
const closeEnd = raw.indexOf("\n", end + 1);
|
|
28
|
+
return raw.slice(closeEnd === -1 ? raw.length : closeEnd + 1).trimStart();
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
function escapeHtml(value: string) {
|
|
32
|
+
return String(value)
|
|
33
|
+
.replace(/&/g, "&")
|
|
34
|
+
.replace(/</g, "<")
|
|
35
|
+
.replace(/>/g, ">")
|
|
36
|
+
.replace(/"/g, """);
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
function stripInlineMarkdown(value: string) {
|
|
40
|
+
return String(value)
|
|
41
|
+
.replace(/\s+\{#[A-Za-z0-9_-]+\}\s*$/, "")
|
|
42
|
+
.replace(/`([^`]+)`/g, "$1")
|
|
43
|
+
.replace(/\*\*([^*]+)\*\*/g, "$1")
|
|
44
|
+
.replace(/\*([^*]+)\*/g, "$1")
|
|
45
|
+
.replace(/\[([^\]]+)\]\([^)]+\)/g, "$1")
|
|
46
|
+
.replace(/<[^>]+>/g, "")
|
|
47
|
+
.replace(/\s+#+\s*$/, "")
|
|
48
|
+
.trim();
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
function slugText(value: string) {
|
|
52
|
+
const slug = String(value)
|
|
53
|
+
.toLowerCase()
|
|
54
|
+
.replace(/[`"'\u2018\u2019\u201c\u201d]/g, "")
|
|
55
|
+
.replace(/[^a-z0-9\u4e00-\u9fa5]+/g, "-")
|
|
56
|
+
.replace(/^-+|-+$/g, "");
|
|
57
|
+
return slug || "section";
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
function createHeadingIdGenerator() {
|
|
61
|
+
const counts = new Map<string, number>();
|
|
62
|
+
return (rawTitle: string) => {
|
|
63
|
+
const explicit = rawTitle.match(/\s+\{#([A-Za-z0-9_-]+)\}\s*$/)?.[1] ?? "";
|
|
64
|
+
const base = explicit || slugText(stripInlineMarkdown(rawTitle));
|
|
65
|
+
const count = counts.get(base) ?? 0;
|
|
66
|
+
counts.set(base, count + 1);
|
|
67
|
+
return count ? `${base}-${count + 1}` : base;
|
|
68
|
+
};
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
function normalizeHeadingAnchors(markdown: string) {
|
|
72
|
+
const nextId = createHeadingIdGenerator();
|
|
73
|
+
let fence: { char: string; length: number } | null = null;
|
|
74
|
+
|
|
75
|
+
return String(markdown ?? "")
|
|
76
|
+
.split(/\n/)
|
|
77
|
+
.map((line) => {
|
|
78
|
+
const marker = String(line).match(/^[ \t]{0,3}(`{3,}|~{3,})/);
|
|
79
|
+
if (fence) {
|
|
80
|
+
if (marker && marker[1][0] === fence.char && marker[1].length >= fence.length) fence = null;
|
|
81
|
+
return line;
|
|
82
|
+
}
|
|
83
|
+
if (marker) {
|
|
84
|
+
fence = { char: marker[1][0], length: marker[1].length };
|
|
85
|
+
return line;
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
const heading = String(line).match(/^(#{1,6})[ \t]+(.+)$/);
|
|
89
|
+
if (!heading) return line;
|
|
90
|
+
const rawTitle = heading[2].replace(/\s+#+\s*$/, "");
|
|
91
|
+
const renderedTitle = rawTitle.replace(/\s+\{#[A-Za-z0-9_-]+\}\s*$/, "").trim();
|
|
92
|
+
return `<span id="${escapeHtml(nextId(rawTitle))}" class="slex-doc-heading-anchor"></span>\n${heading[1]} ${renderedTitle}`;
|
|
93
|
+
})
|
|
94
|
+
.join("\n");
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
function previewMarkdown(value: string) {
|
|
98
|
+
return normalizeHeadingAnchors(stripFrontmatter(value));
|
|
99
|
+
}
|
|
18
100
|
</script>
|
|
19
101
|
|
|
20
|
-
<div class="slex-doc-streamdown">
|
|
21
|
-
<SvelteMarkdown source={content} {extensions} {renderers}>
|
|
102
|
+
<div class="slex-doc-prose slex-doc-streamdown">
|
|
103
|
+
<SvelteMarkdown source={previewMarkdown(content)} {extensions} {renderers} {options}>
|
|
22
104
|
{#snippet code({ lang, text })}
|
|
23
105
|
<PlaygroundSlexCode {lang} {text} {domain} />
|
|
24
106
|
{/snippet}
|
|
@@ -1,104 +1,104 @@
|
|
|
1
|
-
.slex-button {
|
|
2
|
-
display: inline-flex;
|
|
3
|
-
align-items: center;
|
|
4
|
-
justify-content: center;
|
|
5
|
-
gap: 0.5rem;
|
|
6
|
-
max-width: 100%;
|
|
7
|
-
min-width: 0;
|
|
8
|
-
padding: 0.5rem 1rem;
|
|
9
|
-
border: 1px solid transparent;
|
|
10
|
-
border-radius: var(--radius);
|
|
11
|
-
font-family: inherit;
|
|
12
|
-
font-size: 0.875rem;
|
|
13
|
-
font-weight: 500;
|
|
14
|
-
line-height: 1.25;
|
|
15
|
-
white-space: nowrap;
|
|
16
|
-
text-overflow: ellipsis;
|
|
17
|
-
overflow: hidden;
|
|
18
|
-
cursor: pointer;
|
|
19
|
-
user-select: none;
|
|
20
|
-
transition:
|
|
21
|
-
background 150ms ease,
|
|
22
|
-
border-color 150ms ease,
|
|
23
|
-
color 150ms ease,
|
|
24
|
-
box-shadow 150ms ease,
|
|
25
|
-
transform 150ms ease;
|
|
26
|
-
}
|
|
27
|
-
|
|
28
|
-
.slex-button--primary {
|
|
29
|
-
background: var(--primary);
|
|
30
|
-
color: var(--primary-foreground);
|
|
31
|
-
border-color: var(--primary);
|
|
32
|
-
}
|
|
33
|
-
|
|
34
|
-
.slex-button--primary:hover:not(:disabled):not(.slex-button--disabled) {
|
|
35
|
-
background: color-mix(in oklab, var(--primary) 90%, transparent);
|
|
36
|
-
border-color: color-mix(in oklab, var(--primary) 90%, transparent);
|
|
37
|
-
color: var(--primary-foreground);
|
|
38
|
-
transform: translateY(-1px);
|
|
39
|
-
box-shadow: var(--shadow-md);
|
|
40
|
-
}
|
|
41
|
-
|
|
42
|
-
.slex-button--secondary {
|
|
43
|
-
background: var(--secondary);
|
|
44
|
-
color: var(--secondary-foreground);
|
|
45
|
-
border-color: var(--border);
|
|
46
|
-
}
|
|
47
|
-
|
|
48
|
-
.slex-button--secondary:hover:not(:disabled):not(.slex-button--disabled) {
|
|
49
|
-
background: var(--accent);
|
|
50
|
-
color: var(--accent-foreground);
|
|
51
|
-
border-color: var(--border);
|
|
52
|
-
}
|
|
53
|
-
|
|
54
|
-
.slex-button--danger {
|
|
55
|
-
background: var(--destructive);
|
|
56
|
-
color: var(--destructive-foreground);
|
|
57
|
-
border-color: var(--destructive);
|
|
58
|
-
}
|
|
59
|
-
|
|
60
|
-
.slex-button--danger:hover:not(:disabled):not(.slex-button--disabled) {
|
|
61
|
-
background: color-mix(in oklab, var(--destructive) 90%, transparent);
|
|
62
|
-
border-color: color-mix(in oklab, var(--destructive) 90%, transparent);
|
|
63
|
-
}
|
|
64
|
-
|
|
65
|
-
.slex-button--ghost {
|
|
66
|
-
background: transparent;
|
|
67
|
-
color: var(--muted-foreground);
|
|
68
|
-
border-color: transparent;
|
|
69
|
-
}
|
|
70
|
-
|
|
71
|
-
.slex-button--ghost:hover:not(:disabled):not(.slex-button--disabled) {
|
|
72
|
-
background: var(--accent);
|
|
73
|
-
color: var(--accent-foreground);
|
|
74
|
-
}
|
|
75
|
-
|
|
76
|
-
.slex-button:disabled,
|
|
77
|
-
.slex-button[disabled],
|
|
78
|
-
.slex-button--disabled {
|
|
79
|
-
opacity: 0.5;
|
|
80
|
-
cursor: not-allowed;
|
|
81
|
-
pointer-events: none;
|
|
82
|
-
transform: none;
|
|
83
|
-
box-shadow: none;
|
|
84
|
-
}
|
|
85
|
-
|
|
86
|
-
.slex-button:active:not(:disabled):not(.slex-button--disabled) {
|
|
87
|
-
transform: translateY(0);
|
|
88
|
-
box-shadow: var(--shadow-sm);
|
|
89
|
-
}
|
|
90
|
-
|
|
91
|
-
.slex-button:focus-visible {
|
|
92
|
-
outline: 2px solid var(--ring);
|
|
93
|
-
outline-offset: 2px;
|
|
94
|
-
}
|
|
95
|
-
|
|
96
|
-
.slex-button--icon {
|
|
97
|
-
width: var(--slex-control-height, 2.25rem);
|
|
98
|
-
min-height: var(--slex-control-height, 2.25rem);
|
|
99
|
-
padding-inline: 0;
|
|
100
|
-
}
|
|
101
|
-
|
|
1
|
+
.slex-button {
|
|
2
|
+
display: inline-flex;
|
|
3
|
+
align-items: center;
|
|
4
|
+
justify-content: center;
|
|
5
|
+
gap: 0.5rem;
|
|
6
|
+
max-width: 100%;
|
|
7
|
+
min-width: 0;
|
|
8
|
+
padding: 0.5rem 1rem;
|
|
9
|
+
border: 1px solid transparent;
|
|
10
|
+
border-radius: var(--radius);
|
|
11
|
+
font-family: inherit;
|
|
12
|
+
font-size: 0.875rem;
|
|
13
|
+
font-weight: 500;
|
|
14
|
+
line-height: 1.25;
|
|
15
|
+
white-space: nowrap;
|
|
16
|
+
text-overflow: ellipsis;
|
|
17
|
+
overflow: hidden;
|
|
18
|
+
cursor: pointer;
|
|
19
|
+
user-select: none;
|
|
20
|
+
transition:
|
|
21
|
+
background 150ms ease,
|
|
22
|
+
border-color 150ms ease,
|
|
23
|
+
color 150ms ease,
|
|
24
|
+
box-shadow 150ms ease,
|
|
25
|
+
transform 150ms ease;
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
.slex-button--primary {
|
|
29
|
+
background: var(--primary);
|
|
30
|
+
color: var(--primary-foreground);
|
|
31
|
+
border-color: var(--primary);
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
.slex-button--primary:hover:not(:disabled):not(.slex-button--disabled) {
|
|
35
|
+
background: color-mix(in oklab, var(--primary) 90%, transparent);
|
|
36
|
+
border-color: color-mix(in oklab, var(--primary) 90%, transparent);
|
|
37
|
+
color: var(--primary-foreground);
|
|
38
|
+
transform: translateY(-1px);
|
|
39
|
+
box-shadow: var(--shadow-md);
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
.slex-button--secondary {
|
|
43
|
+
background: var(--secondary);
|
|
44
|
+
color: var(--secondary-foreground);
|
|
45
|
+
border-color: var(--border);
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
.slex-button--secondary:hover:not(:disabled):not(.slex-button--disabled) {
|
|
49
|
+
background: var(--accent);
|
|
50
|
+
color: var(--accent-foreground);
|
|
51
|
+
border-color: var(--border);
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
.slex-button--danger {
|
|
55
|
+
background: var(--destructive);
|
|
56
|
+
color: var(--destructive-foreground);
|
|
57
|
+
border-color: var(--destructive);
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
.slex-button--danger:hover:not(:disabled):not(.slex-button--disabled) {
|
|
61
|
+
background: color-mix(in oklab, var(--destructive) 90%, transparent);
|
|
62
|
+
border-color: color-mix(in oklab, var(--destructive) 90%, transparent);
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
.slex-button--ghost {
|
|
66
|
+
background: transparent;
|
|
67
|
+
color: var(--muted-foreground);
|
|
68
|
+
border-color: transparent;
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
.slex-button--ghost:hover:not(:disabled):not(.slex-button--disabled) {
|
|
72
|
+
background: var(--accent);
|
|
73
|
+
color: var(--accent-foreground);
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
.slex-button:disabled,
|
|
77
|
+
.slex-button[disabled],
|
|
78
|
+
.slex-button--disabled {
|
|
79
|
+
opacity: 0.5;
|
|
80
|
+
cursor: not-allowed;
|
|
81
|
+
pointer-events: none;
|
|
82
|
+
transform: none;
|
|
83
|
+
box-shadow: none;
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
.slex-button:active:not(:disabled):not(.slex-button--disabled) {
|
|
87
|
+
transform: translateY(0);
|
|
88
|
+
box-shadow: var(--shadow-sm);
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
.slex-button:focus-visible {
|
|
92
|
+
outline: 2px solid var(--ring);
|
|
93
|
+
outline-offset: 2px;
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
.slex-button--icon {
|
|
97
|
+
width: var(--slex-control-height, 2.25rem);
|
|
98
|
+
min-height: var(--slex-control-height, 2.25rem);
|
|
99
|
+
padding-inline: 0;
|
|
100
|
+
}
|
|
101
|
+
|
|
102
102
|
.slex-button-icon {
|
|
103
103
|
display: inline-flex;
|
|
104
104
|
width: 1.125rem;
|