@nucel/ui 0.2.0 → 0.10.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/package.json +8 -32
- package/src/lib/components/BottomSheet.svelte +96 -0
- package/src/lib/components/Breadcrumbs.svelte +57 -0
- package/src/lib/components/Checkbox.svelte +64 -0
- package/src/lib/components/CodeBlock.svelte +264 -0
- package/src/lib/components/CodeEditor.svelte +175 -0
- package/src/lib/components/ColorInput.svelte +41 -0
- package/src/lib/components/ColorInput.test.ts +126 -0
- package/src/lib/components/Combobox.svelte +103 -0
- package/src/lib/components/CommandPalette.svelte +135 -0
- package/src/lib/components/CopyButton.svelte +95 -0
- package/src/lib/components/CopyButton.test.ts +213 -0
- package/src/lib/components/DataTable.svelte +202 -0
- package/src/lib/components/DateRangePicker.svelte +185 -0
- package/src/lib/components/DiffEditor.svelte +174 -0
- package/src/lib/components/Drawer.svelte +69 -0
- package/src/lib/components/Fab.svelte +59 -0
- package/src/lib/components/Form.svelte +38 -0
- package/src/lib/components/FormField.svelte +51 -0
- package/src/lib/components/IconButton.svelte +86 -0
- package/src/lib/components/IconButton.test.ts +139 -0
- package/src/lib/components/InlineCode.svelte +28 -0
- package/src/lib/components/Pagination.svelte +65 -0
- package/src/lib/components/Radio.svelte +60 -0
- package/src/lib/components/RadioGroup.svelte +26 -0
- package/src/lib/components/SearchInput.svelte +77 -0
- package/src/lib/components/Skeleton.svelte +76 -0
- package/src/lib/components/StatCard.svelte +97 -0
- package/src/lib/components/ThemeProvider.svelte +157 -0
- package/src/lib/components/ThemeToggle.svelte +68 -0
- package/src/lib/components/ThreeWayMerge.svelte +185 -0
- package/src/lib/components/ui/MarkdownRenderer.svelte +126 -8
- package/src/lib/components/ui/Sparkline.svelte +1 -1
- package/src/lib/components/ui/StatusBadge.svelte +6 -3
- package/src/lib/components/ui/StatusDot.svelte +3 -3
- package/src/lib/index.ts +120 -45
- package/src/lib/utils/detectLanguage.ts +187 -0
- package/src/lib/utils/monaco-workers.d.ts +32 -0
- package/src/lib/utils/monacoLoader.ts +167 -0
- package/src/lib/utils/shikiHighlighter.ts +78 -0
- package/src/styles.css +100 -32
- package/src/lib/components/ui/Alert.svelte +0 -47
- package/src/lib/components/ui/Alert.test.ts +0 -206
- package/src/lib/components/ui/AppCard.svelte +0 -76
- package/src/lib/components/ui/AppShell.svelte +0 -14
- package/src/lib/components/ui/AppSidebar.svelte +0 -45
- package/src/lib/components/ui/BranchPill.svelte +0 -19
- package/src/lib/components/ui/BranchPill.test.ts +0 -121
- package/src/lib/components/ui/CommentPill.svelte +0 -12
- package/src/lib/components/ui/CostDisplay.svelte +0 -26
- package/src/lib/components/ui/CostDisplay.test.ts +0 -1115
- package/src/lib/components/ui/FormField.svelte +0 -34
- package/src/lib/components/ui/FormField.test.ts +0 -41
- package/src/lib/components/ui/ListCard.svelte +0 -9
- package/src/lib/components/ui/NavItem.svelte +0 -42
- package/src/lib/components/ui/NavSection.svelte +0 -17
- package/src/lib/components/ui/PageHeader.svelte +0 -25
- package/src/lib/components/ui/PageHeader.test.ts +0 -72
- package/src/lib/components/ui/PermissionChips.svelte +0 -49
- package/src/lib/components/ui/ProgressRing.test.ts +0 -239
- package/src/lib/components/ui/Section.svelte +0 -21
- package/src/lib/components/ui/Section.test.ts +0 -44
- package/src/lib/components/ui/SectionTitle.svelte +0 -16
- package/src/lib/components/ui/StatCard.svelte +0 -19
- package/src/lib/components/ui/StatusBadge.test.ts +0 -150
- package/src/lib/components/ui/StatusPill.svelte +0 -54
- package/src/lib/components/ui/StatusPill.test.ts +0 -125
- package/src/lib/components/ui/editor/RichEditor.svelte +0 -580
- package/src/lib/components/ui/editor/mention-suggestion.ts +0 -144
- package/src/lib/components/ui/table/Table.svelte +0 -12
- package/src/lib/components/ui/table/Table.test.ts +0 -317
- package/src/lib/components/ui/table/TableBody.svelte +0 -10
- package/src/lib/components/ui/table/TableCaption.svelte +0 -10
- package/src/lib/components/ui/table/TableCell.svelte +0 -10
- package/src/lib/components/ui/table/TableHead.svelte +0 -10
- package/src/lib/components/ui/table/TableHeader.svelte +0 -10
- package/src/lib/components/ui/table/TableRow.svelte +0 -10
- package/src/lib/components/ui/table/index.ts +0 -7
|
@@ -1,144 +0,0 @@
|
|
|
1
|
-
import tippy, { type Instance, type Props as TippyProps } from 'tippy.js';
|
|
2
|
-
|
|
3
|
-
export type MentionItem = {
|
|
4
|
-
id: string;
|
|
5
|
-
label: string;
|
|
6
|
-
type?: 'user' | 'team';
|
|
7
|
-
slug?: string;
|
|
8
|
-
avatar_url?: string;
|
|
9
|
-
sublabel?: string;
|
|
10
|
-
};
|
|
11
|
-
|
|
12
|
-
function escapeHtml(text: string): string {
|
|
13
|
-
const div = document.createElement('div');
|
|
14
|
-
div.textContent = text;
|
|
15
|
-
return div.innerHTML;
|
|
16
|
-
}
|
|
17
|
-
|
|
18
|
-
function getInitials(name: string): string {
|
|
19
|
-
return name.split(' ').map(p => p.charAt(0)).join('').toUpperCase().slice(0, 2);
|
|
20
|
-
}
|
|
21
|
-
|
|
22
|
-
function createDropdown(props: { items: MentionItem[]; command: (item: MentionItem) => void }) {
|
|
23
|
-
const el = document.createElement('div');
|
|
24
|
-
el.className = 'mention-list';
|
|
25
|
-
let selectedIndex = 0;
|
|
26
|
-
let items = props.items;
|
|
27
|
-
let command = props.command;
|
|
28
|
-
|
|
29
|
-
function render() {
|
|
30
|
-
if (items.length === 0) {
|
|
31
|
-
el.innerHTML = `<div class="mention-list-empty">No results</div>`;
|
|
32
|
-
return;
|
|
33
|
-
}
|
|
34
|
-
if (items.length === 1 && (items[0] as any).type === 'hint') {
|
|
35
|
-
el.innerHTML = `<div class="mention-list-empty">${escapeHtml(items[0].label)}</div>`;
|
|
36
|
-
return;
|
|
37
|
-
}
|
|
38
|
-
el.innerHTML = items.map((item, i) => `
|
|
39
|
-
<button type="button" class="mention-list-item ${i === selectedIndex ? 'is-selected' : ''}" data-index="${i}">
|
|
40
|
-
${item.avatar_url
|
|
41
|
-
? `<img src="${escapeHtml(item.avatar_url)}" alt="" class="mention-avatar" />`
|
|
42
|
-
: `<span class="mention-avatar-fallback">${getInitials(item.label)}</span>`
|
|
43
|
-
}
|
|
44
|
-
<span class="mention-info">
|
|
45
|
-
<span class="mention-label">${escapeHtml(item.label)}</span>
|
|
46
|
-
${item.sublabel ? `<span class="mention-sublabel">${escapeHtml(item.sublabel)}</span>` : ''}
|
|
47
|
-
</span>
|
|
48
|
-
${item.type === 'team' ? `<span class="mention-badge">Team</span>` : ''}
|
|
49
|
-
</button>
|
|
50
|
-
`).join('');
|
|
51
|
-
|
|
52
|
-
el.querySelectorAll('.mention-list-item').forEach(btn => {
|
|
53
|
-
btn.addEventListener('click', () => {
|
|
54
|
-
const idx = parseInt((btn as HTMLElement).dataset.index ?? '0');
|
|
55
|
-
select(idx);
|
|
56
|
-
});
|
|
57
|
-
});
|
|
58
|
-
}
|
|
59
|
-
|
|
60
|
-
function select(idx: number) {
|
|
61
|
-
const item = items[idx];
|
|
62
|
-
if (item) command(item);
|
|
63
|
-
}
|
|
64
|
-
|
|
65
|
-
function updateSelection(idx: number) {
|
|
66
|
-
selectedIndex = ((idx % items.length) + items.length) % items.length;
|
|
67
|
-
render();
|
|
68
|
-
}
|
|
69
|
-
|
|
70
|
-
render();
|
|
71
|
-
|
|
72
|
-
return {
|
|
73
|
-
el,
|
|
74
|
-
update(newItems: MentionItem[], newCommand: (item: MentionItem) => void) {
|
|
75
|
-
items = newItems;
|
|
76
|
-
command = newCommand;
|
|
77
|
-
selectedIndex = 0;
|
|
78
|
-
render();
|
|
79
|
-
},
|
|
80
|
-
onKeyDown(key: string): boolean {
|
|
81
|
-
if (key === 'ArrowUp') { updateSelection(selectedIndex - 1); return true; }
|
|
82
|
-
if (key === 'ArrowDown') { updateSelection(selectedIndex + 1); return true; }
|
|
83
|
-
if (key === 'Enter') { select(selectedIndex); return true; }
|
|
84
|
-
return false;
|
|
85
|
-
},
|
|
86
|
-
};
|
|
87
|
-
}
|
|
88
|
-
|
|
89
|
-
export function createMentionSuggestion(mentionsUrl: string) {
|
|
90
|
-
return {
|
|
91
|
-
char: '@',
|
|
92
|
-
allowSpaces: false,
|
|
93
|
-
items: async ({ query }: { query: string }): Promise<MentionItem[]> => {
|
|
94
|
-
if (!query || query.length < 1) {
|
|
95
|
-
return [{ id: 'hint', label: 'Type to search users…', type: 'user' } as any];
|
|
96
|
-
}
|
|
97
|
-
try {
|
|
98
|
-
const sep = mentionsUrl.includes('?') ? '&' : '?';
|
|
99
|
-
const res = await fetch(`${mentionsUrl}${sep}query=${encodeURIComponent(query)}`, {
|
|
100
|
-
headers: { Accept: 'application/json' },
|
|
101
|
-
});
|
|
102
|
-
if (!res.ok) return [];
|
|
103
|
-
const data = await res.json();
|
|
104
|
-
return Array.isArray(data.suggestions) ? data.suggestions : [];
|
|
105
|
-
} catch {
|
|
106
|
-
return [];
|
|
107
|
-
}
|
|
108
|
-
},
|
|
109
|
-
render: () => {
|
|
110
|
-
let dropdown: ReturnType<typeof createDropdown>;
|
|
111
|
-
let popup: Instance<TippyProps>[];
|
|
112
|
-
|
|
113
|
-
return {
|
|
114
|
-
onStart(props: any) {
|
|
115
|
-
dropdown = createDropdown({ items: props.items, command: (item) => props.command({ id: item.id, label: item.label, type: item.type, slug: item.slug }) });
|
|
116
|
-
if (!props.clientRect) return;
|
|
117
|
-
popup = tippy('body', {
|
|
118
|
-
getReferenceClientRect: props.clientRect,
|
|
119
|
-
appendTo: () => document.body,
|
|
120
|
-
content: dropdown.el,
|
|
121
|
-
showOnCreate: true,
|
|
122
|
-
interactive: true,
|
|
123
|
-
trigger: 'manual',
|
|
124
|
-
placement: 'bottom-start',
|
|
125
|
-
}) as Instance<TippyProps>[];
|
|
126
|
-
},
|
|
127
|
-
onUpdate(props: any) {
|
|
128
|
-
dropdown.update(props.items, (item) => props.command({ id: item.id, label: item.label, type: item.type, slug: item.slug }));
|
|
129
|
-
if (props.clientRect && popup?.[0]) {
|
|
130
|
-
popup[0].setProps({ getReferenceClientRect: props.clientRect });
|
|
131
|
-
}
|
|
132
|
-
},
|
|
133
|
-
onKeyDown(props: any) {
|
|
134
|
-
if (props.event.key === 'Escape') { popup?.[0]?.hide(); return true; }
|
|
135
|
-
return dropdown.onKeyDown(props.event.key);
|
|
136
|
-
},
|
|
137
|
-
onExit() {
|
|
138
|
-
popup?.[0]?.destroy();
|
|
139
|
-
dropdown.el.remove();
|
|
140
|
-
},
|
|
141
|
-
};
|
|
142
|
-
},
|
|
143
|
-
};
|
|
144
|
-
}
|
|
@@ -1,12 +0,0 @@
|
|
|
1
|
-
<script lang="ts">
|
|
2
|
-
import type { Snippet } from 'svelte';
|
|
3
|
-
import { cn } from '$lib/utils/cn.js';
|
|
4
|
-
|
|
5
|
-
let { children, class: className }: { children: Snippet; class?: string } = $props();
|
|
6
|
-
</script>
|
|
7
|
-
|
|
8
|
-
<div class={cn("w-full overflow-auto", className)}>
|
|
9
|
-
<table class="w-full caption-bottom text-sm">
|
|
10
|
-
{@render children()}
|
|
11
|
-
</table>
|
|
12
|
-
</div>
|
|
@@ -1,317 +0,0 @@
|
|
|
1
|
-
import { describe, it, expect } from "vitest";
|
|
2
|
-
import { render } from "@testing-library/svelte";
|
|
3
|
-
import Table from "./Table.svelte";
|
|
4
|
-
import TableHeader from "./TableHeader.svelte";
|
|
5
|
-
import TableBody from "./TableBody.svelte";
|
|
6
|
-
import TableRow from "./TableRow.svelte";
|
|
7
|
-
import TableHead from "./TableHead.svelte";
|
|
8
|
-
import TableCell from "./TableCell.svelte";
|
|
9
|
-
import TableCaption from "./TableCaption.svelte";
|
|
10
|
-
|
|
11
|
-
describe("Table", () => {
|
|
12
|
-
it("renders a div wrapper with overflow-auto", () => {
|
|
13
|
-
const { container } = render(Table, {
|
|
14
|
-
props: { children: (() => {}) as any },
|
|
15
|
-
});
|
|
16
|
-
const wrapper = container.querySelector("div");
|
|
17
|
-
expect(wrapper).not.toBeNull();
|
|
18
|
-
expect(wrapper!.className).toContain("overflow-auto");
|
|
19
|
-
});
|
|
20
|
-
|
|
21
|
-
it("renders a table element inside the wrapper", () => {
|
|
22
|
-
const { container } = render(Table, {
|
|
23
|
-
props: { children: (() => {}) as any },
|
|
24
|
-
});
|
|
25
|
-
const table = container.querySelector("table");
|
|
26
|
-
expect(table).not.toBeNull();
|
|
27
|
-
});
|
|
28
|
-
|
|
29
|
-
it("table element has caption-bottom class", () => {
|
|
30
|
-
const { container } = render(Table, {
|
|
31
|
-
props: { children: (() => {}) as any },
|
|
32
|
-
});
|
|
33
|
-
const table = container.querySelector("table");
|
|
34
|
-
expect(table!.className).toContain("caption-bottom");
|
|
35
|
-
});
|
|
36
|
-
|
|
37
|
-
it("table element has text-sm class", () => {
|
|
38
|
-
const { container } = render(Table, {
|
|
39
|
-
props: { children: (() => {}) as any },
|
|
40
|
-
});
|
|
41
|
-
const table = container.querySelector("table");
|
|
42
|
-
expect(table!.className).toContain("text-sm");
|
|
43
|
-
});
|
|
44
|
-
|
|
45
|
-
it("wrapper has w-full class", () => {
|
|
46
|
-
const { container } = render(Table, {
|
|
47
|
-
props: { children: (() => {}) as any },
|
|
48
|
-
});
|
|
49
|
-
const wrapper = container.querySelector("div");
|
|
50
|
-
expect(wrapper!.className).toContain("w-full");
|
|
51
|
-
});
|
|
52
|
-
|
|
53
|
-
it("accepts an extra class on the wrapper", () => {
|
|
54
|
-
const { container } = render(Table, {
|
|
55
|
-
props: { children: (() => {}) as any, class: "my-table-wrapper" },
|
|
56
|
-
});
|
|
57
|
-
const wrapper = container.querySelector("div");
|
|
58
|
-
expect(wrapper!.className).toContain("my-table-wrapper");
|
|
59
|
-
});
|
|
60
|
-
|
|
61
|
-
it("does not lose default classes when class prop is provided", () => {
|
|
62
|
-
const { container } = render(Table, {
|
|
63
|
-
props: { children: (() => {}) as any, class: "extra" },
|
|
64
|
-
});
|
|
65
|
-
const wrapper = container.querySelector("div");
|
|
66
|
-
expect(wrapper!.className).toContain("overflow-auto");
|
|
67
|
-
expect(wrapper!.className).toContain("extra");
|
|
68
|
-
});
|
|
69
|
-
});
|
|
70
|
-
|
|
71
|
-
describe("TableHeader", () => {
|
|
72
|
-
it("renders a thead element", () => {
|
|
73
|
-
const { container } = render(TableHeader, {
|
|
74
|
-
props: { children: (() => {}) as any },
|
|
75
|
-
});
|
|
76
|
-
expect(container.querySelector("thead")).not.toBeNull();
|
|
77
|
-
});
|
|
78
|
-
|
|
79
|
-
it("thead has [&_tr]:border-b class", () => {
|
|
80
|
-
const { container } = render(TableHeader, {
|
|
81
|
-
props: { children: (() => {}) as any },
|
|
82
|
-
});
|
|
83
|
-
const thead = container.querySelector("thead");
|
|
84
|
-
expect(thead!.className).toContain("[&_tr]:border-b");
|
|
85
|
-
});
|
|
86
|
-
|
|
87
|
-
it("thead has [&_tr]:border-border class", () => {
|
|
88
|
-
const { container } = render(TableHeader, {
|
|
89
|
-
props: { children: (() => {}) as any },
|
|
90
|
-
});
|
|
91
|
-
const thead = container.querySelector("thead");
|
|
92
|
-
expect(thead!.className).toContain("[&_tr]:border-border");
|
|
93
|
-
});
|
|
94
|
-
|
|
95
|
-
it("accepts an extra class", () => {
|
|
96
|
-
const { container } = render(TableHeader, {
|
|
97
|
-
props: { children: (() => {}) as any, class: "my-header" },
|
|
98
|
-
});
|
|
99
|
-
const thead = container.querySelector("thead");
|
|
100
|
-
expect(thead!.className).toContain("my-header");
|
|
101
|
-
});
|
|
102
|
-
});
|
|
103
|
-
|
|
104
|
-
describe("TableBody", () => {
|
|
105
|
-
it("renders a tbody element", () => {
|
|
106
|
-
const { container } = render(TableBody, {
|
|
107
|
-
props: { children: (() => {}) as any },
|
|
108
|
-
});
|
|
109
|
-
expect(container.querySelector("tbody")).not.toBeNull();
|
|
110
|
-
});
|
|
111
|
-
|
|
112
|
-
it("tbody has [&_tr:last-child]:border-0 class", () => {
|
|
113
|
-
const { container } = render(TableBody, {
|
|
114
|
-
props: { children: (() => {}) as any },
|
|
115
|
-
});
|
|
116
|
-
const tbody = container.querySelector("tbody");
|
|
117
|
-
expect(tbody!.className).toContain("[&_tr:last-child]:border-0");
|
|
118
|
-
});
|
|
119
|
-
|
|
120
|
-
it("accepts an extra class", () => {
|
|
121
|
-
const { container } = render(TableBody, {
|
|
122
|
-
props: { children: (() => {}) as any, class: "my-body" },
|
|
123
|
-
});
|
|
124
|
-
const tbody = container.querySelector("tbody");
|
|
125
|
-
expect(tbody!.className).toContain("my-body");
|
|
126
|
-
});
|
|
127
|
-
});
|
|
128
|
-
|
|
129
|
-
describe("TableRow", () => {
|
|
130
|
-
it("renders a tr element", () => {
|
|
131
|
-
const { container } = render(TableRow, {
|
|
132
|
-
props: { children: (() => {}) as any },
|
|
133
|
-
});
|
|
134
|
-
expect(container.querySelector("tr")).not.toBeNull();
|
|
135
|
-
});
|
|
136
|
-
|
|
137
|
-
it("tr has border-b class", () => {
|
|
138
|
-
const { container } = render(TableRow, {
|
|
139
|
-
props: { children: (() => {}) as any },
|
|
140
|
-
});
|
|
141
|
-
const tr = container.querySelector("tr");
|
|
142
|
-
expect(tr!.className).toContain("border-b");
|
|
143
|
-
});
|
|
144
|
-
|
|
145
|
-
it("tr has hover:bg-accent/50 class", () => {
|
|
146
|
-
const { container } = render(TableRow, {
|
|
147
|
-
props: { children: (() => {}) as any },
|
|
148
|
-
});
|
|
149
|
-
const tr = container.querySelector("tr");
|
|
150
|
-
expect(tr!.className).toContain("hover:bg-accent/50");
|
|
151
|
-
});
|
|
152
|
-
|
|
153
|
-
it("tr has transition-colors class", () => {
|
|
154
|
-
const { container } = render(TableRow, {
|
|
155
|
-
props: { children: (() => {}) as any },
|
|
156
|
-
});
|
|
157
|
-
const tr = container.querySelector("tr");
|
|
158
|
-
expect(tr!.className).toContain("transition-colors");
|
|
159
|
-
});
|
|
160
|
-
|
|
161
|
-
it("accepts an extra class", () => {
|
|
162
|
-
const { container } = render(TableRow, {
|
|
163
|
-
props: { children: (() => {}) as any, class: "bg-muted/20" },
|
|
164
|
-
});
|
|
165
|
-
const tr = container.querySelector("tr");
|
|
166
|
-
expect(tr!.className).toContain("bg-muted/20");
|
|
167
|
-
});
|
|
168
|
-
|
|
169
|
-
it("does not lose base classes when extra class is added", () => {
|
|
170
|
-
const { container } = render(TableRow, {
|
|
171
|
-
props: { children: (() => {}) as any, class: "extra" },
|
|
172
|
-
});
|
|
173
|
-
const tr = container.querySelector("tr");
|
|
174
|
-
expect(tr!.className).toContain("border-b");
|
|
175
|
-
expect(tr!.className).toContain("extra");
|
|
176
|
-
});
|
|
177
|
-
});
|
|
178
|
-
|
|
179
|
-
describe("TableHead", () => {
|
|
180
|
-
it("renders a th element", () => {
|
|
181
|
-
const { container } = render(TableHead, {
|
|
182
|
-
props: { children: (() => {}) as any },
|
|
183
|
-
});
|
|
184
|
-
expect(container.querySelector("th")).not.toBeNull();
|
|
185
|
-
});
|
|
186
|
-
|
|
187
|
-
it("th has h-9 class", () => {
|
|
188
|
-
const { container } = render(TableHead, {
|
|
189
|
-
props: { children: (() => {}) as any },
|
|
190
|
-
});
|
|
191
|
-
const th = container.querySelector("th");
|
|
192
|
-
expect(th!.className).toContain("h-9");
|
|
193
|
-
});
|
|
194
|
-
|
|
195
|
-
it("th has text-left class", () => {
|
|
196
|
-
const { container } = render(TableHead, {
|
|
197
|
-
props: { children: (() => {}) as any },
|
|
198
|
-
});
|
|
199
|
-
const th = container.querySelector("th");
|
|
200
|
-
expect(th!.className).toContain("text-left");
|
|
201
|
-
});
|
|
202
|
-
|
|
203
|
-
it("th has uppercase class", () => {
|
|
204
|
-
const { container } = render(TableHead, {
|
|
205
|
-
props: { children: (() => {}) as any },
|
|
206
|
-
});
|
|
207
|
-
const th = container.querySelector("th");
|
|
208
|
-
expect(th!.className).toContain("uppercase");
|
|
209
|
-
});
|
|
210
|
-
|
|
211
|
-
it("th has text-muted-foreground class", () => {
|
|
212
|
-
const { container } = render(TableHead, {
|
|
213
|
-
props: { children: (() => {}) as any },
|
|
214
|
-
});
|
|
215
|
-
const th = container.querySelector("th");
|
|
216
|
-
expect(th!.className).toContain("text-muted-foreground");
|
|
217
|
-
});
|
|
218
|
-
|
|
219
|
-
it("accepts an extra class", () => {
|
|
220
|
-
const { container } = render(TableHead, {
|
|
221
|
-
props: { children: (() => {}) as any, class: "w-1/4" },
|
|
222
|
-
});
|
|
223
|
-
const th = container.querySelector("th");
|
|
224
|
-
expect(th!.className).toContain("w-1/4");
|
|
225
|
-
});
|
|
226
|
-
});
|
|
227
|
-
|
|
228
|
-
describe("TableCell", () => {
|
|
229
|
-
it("renders a td element", () => {
|
|
230
|
-
const { container } = render(TableCell, {
|
|
231
|
-
props: { children: (() => {}) as any },
|
|
232
|
-
});
|
|
233
|
-
expect(container.querySelector("td")).not.toBeNull();
|
|
234
|
-
});
|
|
235
|
-
|
|
236
|
-
it("td has px-4 class", () => {
|
|
237
|
-
const { container } = render(TableCell, {
|
|
238
|
-
props: { children: (() => {}) as any },
|
|
239
|
-
});
|
|
240
|
-
const td = container.querySelector("td");
|
|
241
|
-
expect(td!.className).toContain("px-4");
|
|
242
|
-
});
|
|
243
|
-
|
|
244
|
-
it("td has py-2.5 class", () => {
|
|
245
|
-
const { container } = render(TableCell, {
|
|
246
|
-
props: { children: (() => {}) as any },
|
|
247
|
-
});
|
|
248
|
-
const td = container.querySelector("td");
|
|
249
|
-
expect(td!.className).toContain("py-2.5");
|
|
250
|
-
});
|
|
251
|
-
|
|
252
|
-
it("td has align-middle class", () => {
|
|
253
|
-
const { container } = render(TableCell, {
|
|
254
|
-
props: { children: (() => {}) as any },
|
|
255
|
-
});
|
|
256
|
-
const td = container.querySelector("td");
|
|
257
|
-
expect(td!.className).toContain("align-middle");
|
|
258
|
-
});
|
|
259
|
-
|
|
260
|
-
it("accepts an extra class", () => {
|
|
261
|
-
const { container } = render(TableCell, {
|
|
262
|
-
props: { children: (() => {}) as any, class: "font-mono" },
|
|
263
|
-
});
|
|
264
|
-
const td = container.querySelector("td");
|
|
265
|
-
expect(td!.className).toContain("font-mono");
|
|
266
|
-
});
|
|
267
|
-
|
|
268
|
-
it("does not lose base classes when extra class is added", () => {
|
|
269
|
-
const { container } = render(TableCell, {
|
|
270
|
-
props: { children: (() => {}) as any, class: "extra" },
|
|
271
|
-
});
|
|
272
|
-
const td = container.querySelector("td");
|
|
273
|
-
expect(td!.className).toContain("px-4");
|
|
274
|
-
expect(td!.className).toContain("extra");
|
|
275
|
-
});
|
|
276
|
-
});
|
|
277
|
-
|
|
278
|
-
describe("TableCaption", () => {
|
|
279
|
-
it("renders a caption element", () => {
|
|
280
|
-
const { container } = render(TableCaption, {
|
|
281
|
-
props: { children: (() => {}) as any },
|
|
282
|
-
});
|
|
283
|
-
expect(container.querySelector("caption")).not.toBeNull();
|
|
284
|
-
});
|
|
285
|
-
|
|
286
|
-
it("caption has mt-4 class", () => {
|
|
287
|
-
const { container } = render(TableCaption, {
|
|
288
|
-
props: { children: (() => {}) as any },
|
|
289
|
-
});
|
|
290
|
-
const caption = container.querySelector("caption");
|
|
291
|
-
expect(caption!.className).toContain("mt-4");
|
|
292
|
-
});
|
|
293
|
-
|
|
294
|
-
it("caption has text-xs class", () => {
|
|
295
|
-
const { container } = render(TableCaption, {
|
|
296
|
-
props: { children: (() => {}) as any },
|
|
297
|
-
});
|
|
298
|
-
const caption = container.querySelector("caption");
|
|
299
|
-
expect(caption!.className).toContain("text-xs");
|
|
300
|
-
});
|
|
301
|
-
|
|
302
|
-
it("caption has text-muted-foreground class", () => {
|
|
303
|
-
const { container } = render(TableCaption, {
|
|
304
|
-
props: { children: (() => {}) as any },
|
|
305
|
-
});
|
|
306
|
-
const caption = container.querySelector("caption");
|
|
307
|
-
expect(caption!.className).toContain("text-muted-foreground");
|
|
308
|
-
});
|
|
309
|
-
|
|
310
|
-
it("accepts an extra class", () => {
|
|
311
|
-
const { container } = render(TableCaption, {
|
|
312
|
-
props: { children: (() => {}) as any, class: "italic" },
|
|
313
|
-
});
|
|
314
|
-
const caption = container.querySelector("caption");
|
|
315
|
-
expect(caption!.className).toContain("italic");
|
|
316
|
-
});
|
|
317
|
-
});
|
|
@@ -1,10 +0,0 @@
|
|
|
1
|
-
<script lang="ts">
|
|
2
|
-
import type { Snippet } from 'svelte';
|
|
3
|
-
import { cn } from '$lib/utils/cn.js';
|
|
4
|
-
|
|
5
|
-
let { children, class: className }: { children: Snippet; class?: string } = $props();
|
|
6
|
-
</script>
|
|
7
|
-
|
|
8
|
-
<tbody class={cn("[&_tr:last-child]:border-0", className)}>
|
|
9
|
-
{@render children()}
|
|
10
|
-
</tbody>
|
|
@@ -1,10 +0,0 @@
|
|
|
1
|
-
<script lang="ts">
|
|
2
|
-
import type { Snippet } from 'svelte';
|
|
3
|
-
import { cn } from '$lib/utils/cn.js';
|
|
4
|
-
|
|
5
|
-
let { children, class: className }: { children: Snippet; class?: string } = $props();
|
|
6
|
-
</script>
|
|
7
|
-
|
|
8
|
-
<caption class={cn("mt-4 text-xs text-muted-foreground", className)}>
|
|
9
|
-
{@render children()}
|
|
10
|
-
</caption>
|
|
@@ -1,10 +0,0 @@
|
|
|
1
|
-
<script lang="ts">
|
|
2
|
-
import type { Snippet } from 'svelte';
|
|
3
|
-
import { cn } from '$lib/utils/cn.js';
|
|
4
|
-
|
|
5
|
-
let { children, class: className, ...rest }: { children?: Snippet; class?: string; [key: string]: unknown } = $props();
|
|
6
|
-
</script>
|
|
7
|
-
|
|
8
|
-
<td class={cn("px-4 py-2.5 align-middle [&:has([role=checkbox])]:pr-0", className)} {...rest}>
|
|
9
|
-
{@render children?.()}
|
|
10
|
-
</td>
|
|
@@ -1,10 +0,0 @@
|
|
|
1
|
-
<script lang="ts">
|
|
2
|
-
import type { Snippet } from 'svelte';
|
|
3
|
-
import { cn } from '$lib/utils/cn.js';
|
|
4
|
-
|
|
5
|
-
let { children, class: className, ...rest }: { children?: Snippet; class?: string; [key: string]: unknown } = $props();
|
|
6
|
-
</script>
|
|
7
|
-
|
|
8
|
-
<th class={cn("h-9 px-4 text-left align-middle text-[10px] font-semibold uppercase tracking-wide text-muted-foreground [&:has([role=checkbox])]:pr-0", className)} {...rest}>
|
|
9
|
-
{@render children?.()}
|
|
10
|
-
</th>
|
|
@@ -1,10 +0,0 @@
|
|
|
1
|
-
<script lang="ts">
|
|
2
|
-
import type { Snippet } from 'svelte';
|
|
3
|
-
import { cn } from '$lib/utils/cn.js';
|
|
4
|
-
|
|
5
|
-
let { children, class: className }: { children: Snippet; class?: string } = $props();
|
|
6
|
-
</script>
|
|
7
|
-
|
|
8
|
-
<thead class={cn("[&_tr]:border-b [&_tr]:border-border", className)}>
|
|
9
|
-
{@render children()}
|
|
10
|
-
</thead>
|
|
@@ -1,10 +0,0 @@
|
|
|
1
|
-
<script lang="ts">
|
|
2
|
-
import type { Snippet } from 'svelte';
|
|
3
|
-
import { cn } from '$lib/utils/cn.js';
|
|
4
|
-
|
|
5
|
-
let { children, class: className }: { children: Snippet; class?: string } = $props();
|
|
6
|
-
</script>
|
|
7
|
-
|
|
8
|
-
<tr class={cn("border-b border-border transition-colors hover:bg-accent/50 data-[state=selected]:bg-accent", className)}>
|
|
9
|
-
{@render children()}
|
|
10
|
-
</tr>
|
|
@@ -1,7 +0,0 @@
|
|
|
1
|
-
export { default as Table } from './Table.svelte';
|
|
2
|
-
export { default as TableHeader } from './TableHeader.svelte';
|
|
3
|
-
export { default as TableBody } from './TableBody.svelte';
|
|
4
|
-
export { default as TableRow } from './TableRow.svelte';
|
|
5
|
-
export { default as TableHead } from './TableHead.svelte';
|
|
6
|
-
export { default as TableCell } from './TableCell.svelte';
|
|
7
|
-
export { default as TableCaption } from './TableCaption.svelte';
|