@nqmcreative/ui 0.2.2 → 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/README.md +15 -15
- package/cli/index.mjs +81 -42
- package/dist/core/index.d.ts +1 -1
- package/dist/core/index.js +1 -1
- package/dist/core/toast.svelte.d.ts +3 -0
- package/dist/core/trigger.d.ts +6 -0
- package/dist/core/trigger.js +13 -0
- package/dist/styles/matte/AccordionItem.svelte +5 -0
- package/dist/styles/matte/AccordionItem.svelte.d.ts +2 -0
- package/dist/styles/matte/Avatar.svelte +15 -0
- package/dist/styles/matte/Avatar.svelte.d.ts +3 -0
- package/dist/styles/matte/Badge.svelte +5 -0
- package/dist/styles/matte/Badge.svelte.d.ts +2 -0
- package/dist/styles/matte/Breadcrumb.svelte +11 -4
- package/dist/styles/matte/Breadcrumb.svelte.d.ts +3 -0
- package/dist/styles/matte/Button.svelte +62 -11
- package/dist/styles/matte/Button.svelte.d.ts +14 -2
- package/dist/styles/matte/Card.svelte +9 -4
- package/dist/styles/matte/Card.svelte.d.ts +2 -0
- package/dist/styles/matte/CheckboxGroup.svelte +6 -0
- package/dist/styles/matte/CheckboxGroup.svelte.d.ts +2 -0
- package/dist/styles/matte/Combobox.svelte +7 -2
- package/dist/styles/matte/Combobox.svelte.d.ts +3 -0
- package/dist/styles/matte/CommandPalette.svelte +38 -7
- package/dist/styles/matte/CommandPalette.svelte.d.ts +8 -0
- package/dist/styles/matte/DatePicker.svelte +2 -2
- package/dist/styles/matte/Drawer.svelte +7 -2
- package/dist/styles/matte/Drawer.svelte.d.ts +2 -0
- package/dist/styles/matte/Dropzone.svelte +1 -1
- package/dist/styles/matte/FeatureCard.svelte +1 -1
- package/dist/styles/matte/Footer.svelte +6 -2
- package/dist/styles/matte/Footer.svelte.d.ts +2 -0
- package/dist/styles/matte/Input.svelte +4 -4
- package/dist/styles/matte/Link.svelte +9 -0
- package/dist/styles/matte/Link.svelte.d.ts +4 -0
- package/dist/styles/matte/MenuItem.svelte +3 -2
- package/dist/styles/matte/Modal.svelte +8 -3
- package/dist/styles/matte/Modal.svelte.d.ts +2 -0
- package/dist/styles/matte/MultiSelect.svelte +7 -1
- package/dist/styles/matte/MultiSelect.svelte.d.ts +3 -0
- package/dist/styles/matte/Navbar.svelte +18 -4
- package/dist/styles/matte/Navbar.svelte.d.ts +2 -0
- package/dist/styles/matte/PricingCard.svelte +19 -11
- package/dist/styles/matte/PricingCard.svelte.d.ts +2 -0
- package/dist/styles/matte/RadioGroup.svelte +6 -0
- package/dist/styles/matte/RadioGroup.svelte.d.ts +2 -0
- package/dist/styles/matte/SegmentedControl.svelte +17 -3
- package/dist/styles/matte/SegmentedControl.svelte.d.ts +5 -0
- package/dist/styles/matte/Select.svelte +1 -1
- package/dist/styles/matte/Sidebar.svelte +76 -26
- package/dist/styles/matte/Sidebar.svelte.d.ts +15 -1
- package/dist/styles/matte/Stat.svelte +8 -1
- package/dist/styles/matte/Stat.svelte.d.ts +3 -0
- package/dist/styles/matte/StatsBand.svelte +1 -1
- package/dist/styles/matte/Steps.svelte +7 -0
- package/dist/styles/matte/Steps.svelte.d.ts +3 -0
- package/dist/styles/matte/Table.svelte +154 -98
- package/dist/styles/matte/Table.svelte.d.ts +12 -0
- package/dist/styles/matte/Tabs.svelte +5 -0
- package/dist/styles/matte/Tabs.svelte.d.ts +3 -0
- package/dist/styles/matte/Testimonial.svelte +2 -2
- package/dist/styles/matte/Textarea.svelte +1 -1
- package/dist/styles/matte/Toaster.svelte +3 -0
- package/dist/styles/matte/icon.d.ts +21 -0
- package/dist/styles/matte/icon.js +21 -0
- package/dist/styles/matte/index.d.ts +1 -3
- package/dist/styles/matte/index.js +0 -2
- package/dist/styles/paper/AccordionItem.svelte +5 -0
- package/dist/styles/paper/AccordionItem.svelte.d.ts +2 -0
- package/dist/styles/paper/Avatar.svelte +15 -0
- package/dist/styles/paper/Avatar.svelte.d.ts +3 -0
- package/dist/styles/paper/Badge.svelte +5 -0
- package/dist/styles/paper/Badge.svelte.d.ts +2 -0
- package/dist/styles/paper/Breadcrumb.svelte +8 -4
- package/dist/styles/paper/Breadcrumb.svelte.d.ts +3 -0
- package/dist/styles/paper/Button.svelte +58 -7
- package/dist/styles/paper/Button.svelte.d.ts +14 -2
- package/dist/styles/paper/Card.svelte +6 -1
- package/dist/styles/paper/Card.svelte.d.ts +2 -0
- package/dist/styles/paper/CheckboxGroup.svelte +6 -0
- package/dist/styles/paper/CheckboxGroup.svelte.d.ts +2 -0
- package/dist/styles/paper/Combobox.svelte +5 -0
- package/dist/styles/paper/Combobox.svelte.d.ts +3 -0
- package/dist/styles/paper/CommandPalette.svelte +31 -2
- package/dist/styles/paper/CommandPalette.svelte.d.ts +8 -0
- package/dist/styles/paper/Drawer.svelte +5 -0
- package/dist/styles/paper/Drawer.svelte.d.ts +2 -0
- package/dist/styles/paper/Footer.svelte +6 -2
- package/dist/styles/paper/Footer.svelte.d.ts +2 -0
- package/dist/styles/paper/Link.svelte +9 -0
- package/dist/styles/paper/Link.svelte.d.ts +4 -0
- package/dist/styles/paper/MenuItem.svelte +2 -1
- package/dist/styles/paper/Modal.svelte +14 -1
- package/dist/styles/paper/Modal.svelte.d.ts +2 -0
- package/dist/styles/paper/MultiSelect.svelte +7 -1
- package/dist/styles/paper/MultiSelect.svelte.d.ts +3 -0
- package/dist/styles/paper/Navbar.svelte +18 -4
- package/dist/styles/paper/Navbar.svelte.d.ts +2 -0
- package/dist/styles/paper/PricingCard.svelte +23 -15
- package/dist/styles/paper/PricingCard.svelte.d.ts +2 -0
- package/dist/styles/paper/RadioGroup.svelte +6 -0
- package/dist/styles/paper/RadioGroup.svelte.d.ts +2 -0
- package/dist/styles/paper/SegmentedControl.svelte +16 -2
- package/dist/styles/paper/SegmentedControl.svelte.d.ts +5 -0
- package/dist/styles/paper/Sidebar.svelte +76 -26
- package/dist/styles/paper/Sidebar.svelte.d.ts +15 -1
- package/dist/styles/paper/Stat.svelte +8 -1
- package/dist/styles/paper/Stat.svelte.d.ts +3 -0
- package/dist/styles/paper/Steps.svelte +7 -0
- package/dist/styles/paper/Steps.svelte.d.ts +3 -0
- package/dist/styles/paper/Table.svelte +153 -97
- package/dist/styles/paper/Table.svelte.d.ts +12 -0
- package/dist/styles/paper/Tabs.svelte +5 -0
- package/dist/styles/paper/Tabs.svelte.d.ts +3 -0
- package/dist/styles/paper/Toaster.svelte +3 -0
- package/dist/styles/paper/fonts.css +34 -7
- package/dist/styles/paper/icon.d.ts +21 -0
- package/dist/styles/paper/icon.js +21 -0
- package/dist/styles/paper/index.d.ts +1 -3
- package/dist/styles/paper/index.js +0 -2
- package/dist/styles/paper/theme.css +11 -8
- package/dist/styles/sprout/AccordionItem.svelte +5 -0
- package/dist/styles/sprout/AccordionItem.svelte.d.ts +2 -0
- package/dist/styles/sprout/Avatar.svelte +15 -0
- package/dist/styles/sprout/Avatar.svelte.d.ts +3 -0
- package/dist/styles/sprout/Badge.svelte +5 -0
- package/dist/styles/sprout/Badge.svelte.d.ts +2 -0
- package/dist/styles/sprout/Breadcrumb.svelte +8 -4
- package/dist/styles/sprout/Breadcrumb.svelte.d.ts +3 -0
- package/dist/styles/sprout/Button.svelte +58 -7
- package/dist/styles/sprout/Button.svelte.d.ts +14 -2
- package/dist/styles/sprout/Card.svelte +6 -1
- package/dist/styles/sprout/Card.svelte.d.ts +2 -0
- package/dist/styles/sprout/CheckboxGroup.svelte +6 -0
- package/dist/styles/sprout/CheckboxGroup.svelte.d.ts +2 -0
- package/dist/styles/sprout/Combobox.svelte +5 -0
- package/dist/styles/sprout/Combobox.svelte.d.ts +3 -0
- package/dist/styles/sprout/CommandPalette.svelte +31 -2
- package/dist/styles/sprout/CommandPalette.svelte.d.ts +8 -0
- package/dist/styles/sprout/Drawer.svelte +5 -0
- package/dist/styles/sprout/Drawer.svelte.d.ts +2 -0
- package/dist/styles/sprout/Footer.svelte +6 -2
- package/dist/styles/sprout/Footer.svelte.d.ts +2 -0
- package/dist/styles/sprout/Link.svelte +9 -0
- package/dist/styles/sprout/Link.svelte.d.ts +4 -0
- package/dist/styles/sprout/MenuItem.svelte +2 -1
- package/dist/styles/sprout/Modal.svelte +14 -1
- package/dist/styles/sprout/Modal.svelte.d.ts +2 -0
- package/dist/styles/sprout/MultiSelect.svelte +7 -1
- package/dist/styles/sprout/MultiSelect.svelte.d.ts +3 -0
- package/dist/styles/sprout/Navbar.svelte +18 -4
- package/dist/styles/sprout/Navbar.svelte.d.ts +2 -0
- package/dist/styles/sprout/PricingCard.svelte +23 -15
- package/dist/styles/sprout/PricingCard.svelte.d.ts +2 -0
- package/dist/styles/sprout/RadioGroup.svelte +6 -0
- package/dist/styles/sprout/RadioGroup.svelte.d.ts +2 -0
- package/dist/styles/sprout/SegmentedControl.svelte +16 -2
- package/dist/styles/sprout/SegmentedControl.svelte.d.ts +5 -0
- package/dist/styles/sprout/Sidebar.svelte +76 -26
- package/dist/styles/sprout/Sidebar.svelte.d.ts +15 -1
- package/dist/styles/sprout/Stat.svelte +8 -1
- package/dist/styles/sprout/Stat.svelte.d.ts +3 -0
- package/dist/styles/sprout/Steps.svelte +7 -0
- package/dist/styles/sprout/Steps.svelte.d.ts +3 -0
- package/dist/styles/sprout/Table.svelte +153 -97
- package/dist/styles/sprout/Table.svelte.d.ts +12 -0
- package/dist/styles/sprout/Tabs.svelte +5 -0
- package/dist/styles/sprout/Tabs.svelte.d.ts +3 -0
- package/dist/styles/sprout/Toaster.svelte +3 -0
- package/dist/styles/sprout/fonts.css +7 -8
- package/dist/styles/sprout/icon.d.ts +21 -0
- package/dist/styles/sprout/icon.js +21 -0
- package/dist/styles/sprout/index.d.ts +1 -3
- package/dist/styles/sprout/index.js +0 -2
- package/dist/styles/sprout/theme.css +6 -6
- package/package.json +2 -26
- package/registry.json +3 -36
- package/dist/styles/matte/NumberInput.svelte +0 -96
- package/dist/styles/matte/NumberInput.svelte.d.ts +0 -15
- package/dist/styles/matte/PasswordInput.svelte +0 -95
- package/dist/styles/matte/PasswordInput.svelte.d.ts +0 -12
- package/dist/styles/paper/NumberInput.svelte +0 -96
- package/dist/styles/paper/NumberInput.svelte.d.ts +0 -15
- package/dist/styles/paper/PasswordInput.svelte +0 -100
- package/dist/styles/paper/PasswordInput.svelte.d.ts +0 -12
- package/dist/styles/sprout/NumberInput.svelte +0 -97
- package/dist/styles/sprout/NumberInput.svelte.d.ts +0 -15
- package/dist/styles/sprout/PasswordInput.svelte +0 -101
- package/dist/styles/sprout/PasswordInput.svelte.d.ts +0 -12
|
@@ -33,6 +33,16 @@
|
|
|
33
33
|
/** Header stays put while the body scrolls — pair with a `max-h-*` class. */
|
|
34
34
|
stickyHeader?: boolean;
|
|
35
35
|
|
|
36
|
+
/** Bar above the table — a title, a search field, a filter row. */
|
|
37
|
+
header?: Snippet;
|
|
38
|
+
/** Bar below the table — pagination, a total, a summary line. */
|
|
39
|
+
footer?: Snippet;
|
|
40
|
+
/**
|
|
41
|
+
* Shown in place of `header` while rows are ticked, after the count and the
|
|
42
|
+
* clear button. Passing it is what turns the bulk bar on.
|
|
43
|
+
*/
|
|
44
|
+
bulkActions?: Snippet<[{ selected: string[]; clear: () => void }]>;
|
|
45
|
+
|
|
36
46
|
/** Bindable. Set it to sort; leave `sortable` columns to drive it. */
|
|
37
47
|
sort?: TableSort | null;
|
|
38
48
|
/** Sort the rows here rather than refetching them server-side. Default true. */
|
|
@@ -58,6 +68,9 @@
|
|
|
58
68
|
hoverable = true,
|
|
59
69
|
compact = false,
|
|
60
70
|
stickyHeader = false,
|
|
71
|
+
header,
|
|
72
|
+
footer,
|
|
73
|
+
bulkActions,
|
|
61
74
|
sort = $bindable(null),
|
|
62
75
|
sortLocally = true,
|
|
63
76
|
onsort,
|
|
@@ -107,112 +120,155 @@
|
|
|
107
120
|
selected = toggleKey(selected, keyOf(row));
|
|
108
121
|
onselect?.(selected);
|
|
109
122
|
}
|
|
123
|
+
|
|
124
|
+
function clearSelection() {
|
|
125
|
+
selected = [];
|
|
126
|
+
onselect?.(selected);
|
|
127
|
+
}
|
|
128
|
+
|
|
129
|
+
/** The bulk bar takes the header's place, so only one of the two is up. */
|
|
130
|
+
const bulkBar = $derived(selectable && bulkActions !== undefined && selected.length > 0);
|
|
110
131
|
</script>
|
|
111
132
|
|
|
112
133
|
<div
|
|
113
|
-
class="w-full overflow-
|
|
134
|
+
class="flex w-full flex-col overflow-hidden rounded-[20px] border border-hairline bg-bg {edge} {className}"
|
|
114
135
|
{...rest}
|
|
115
136
|
>
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
137
|
+
{#if bulkBar}
|
|
138
|
+
<div
|
|
139
|
+
class="flex flex-wrap items-center gap-3 border-b border-hairline bg-brand-light px-4 py-3"
|
|
140
|
+
>
|
|
141
|
+
<span class="font-sans text-[13px] font-semibold text-text">
|
|
142
|
+
{selected.length}
|
|
143
|
+
{t.current.selected}
|
|
144
|
+
</span>
|
|
145
|
+
<button
|
|
146
|
+
type="button"
|
|
147
|
+
onclick={clearSelection}
|
|
148
|
+
class="rounded-full font-sans text-[13px] font-medium text-text-muted transition-colors duration-150 hover:text-text focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-current"
|
|
120
149
|
>
|
|
121
|
-
{
|
|
122
|
-
</
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
150
|
+
{t.current.clear}
|
|
151
|
+
</button>
|
|
152
|
+
<div class="ml-auto flex flex-wrap items-center gap-2">
|
|
153
|
+
{@render bulkActions?.({ selected, clear: clearSelection })}
|
|
154
|
+
</div>
|
|
155
|
+
</div>
|
|
156
|
+
{:else if header}
|
|
157
|
+
<div
|
|
158
|
+
class="flex flex-wrap items-center gap-3 border-b border-hairline px-4 py-3 font-sans text-[13px] text-text-secondary"
|
|
159
|
+
>
|
|
160
|
+
{@render header()}
|
|
161
|
+
</div>
|
|
162
|
+
{/if}
|
|
163
|
+
<div class="min-h-0 w-full flex-1 overflow-auto">
|
|
164
|
+
<table class="w-full border-collapse font-sans text-sm">
|
|
165
|
+
{#if caption}
|
|
166
|
+
<caption
|
|
167
|
+
class="border-b border-hairline px-4 py-3 text-left font-sans text-[13px] text-text-muted"
|
|
168
|
+
>
|
|
169
|
+
{caption}
|
|
170
|
+
</caption>
|
|
171
|
+
{/if}
|
|
172
|
+
<thead class={stickyHeader ? 'sticky top-0 z-10' : ''}>
|
|
173
|
+
<tr class="border-b border-hairline bg-bg-alt">
|
|
174
|
+
{#if selectable}
|
|
175
|
+
<th scope="col" class="w-10 {pad}">
|
|
176
|
+
<Checkbox
|
|
177
|
+
checked={allSelected}
|
|
178
|
+
indeterminate={someSelected}
|
|
179
|
+
{tone}
|
|
180
|
+
aria-label={t.current.selectAllRows}
|
|
181
|
+
onchange={toggleAll}
|
|
182
|
+
/>
|
|
183
|
+
</th>
|
|
184
|
+
{/if}
|
|
185
|
+
{#each columns as column (column.key)}
|
|
186
|
+
<th
|
|
187
|
+
scope="col"
|
|
188
|
+
aria-sort={sort?.key === column.key
|
|
189
|
+
? sort.direction === 'asc'
|
|
190
|
+
? 'ascending'
|
|
191
|
+
: 'descending'
|
|
192
|
+
: undefined}
|
|
193
|
+
class="text-[13px] font-semibold text-text-muted {pad} {aligns[
|
|
194
|
+
column.align ?? 'left'
|
|
195
|
+
]} {column.class ?? ''}"
|
|
196
|
+
>
|
|
197
|
+
{#if column.sortable}
|
|
198
|
+
<button
|
|
199
|
+
type="button"
|
|
200
|
+
onclick={() => toggleSort(column)}
|
|
201
|
+
class="inline-flex items-center gap-1.5 rounded transition-colors duration-150 hover:text-text focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-current
|
|
154
202
|
{sort?.key === column.key ? 'text-text' : ''}"
|
|
155
|
-
|
|
203
|
+
>
|
|
204
|
+
{column.label}
|
|
205
|
+
<span class="text-[9px] leading-none" aria-hidden="true">
|
|
206
|
+
{#if sort?.key === column.key}
|
|
207
|
+
{sort.direction === 'asc' ? '▲' : '▼'}
|
|
208
|
+
{:else}
|
|
209
|
+
⇅
|
|
210
|
+
{/if}
|
|
211
|
+
</span>
|
|
212
|
+
</button>
|
|
213
|
+
{:else}
|
|
156
214
|
{column.label}
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
{:else}
|
|
161
|
-
⇅
|
|
162
|
-
{/if}
|
|
163
|
-
</span>
|
|
164
|
-
</button>
|
|
165
|
-
{:else}
|
|
166
|
-
{column.label}
|
|
167
|
-
{/if}
|
|
168
|
-
</th>
|
|
169
|
-
{/each}
|
|
170
|
-
</tr>
|
|
171
|
-
</thead>
|
|
172
|
-
<tbody>
|
|
173
|
-
{#if sorted.length === 0}
|
|
174
|
-
<tr>
|
|
175
|
-
<td
|
|
176
|
-
colspan={columns.length + (selectable ? 1 : 0)}
|
|
177
|
-
class="px-4 py-10 text-center text-sm text-text-muted"
|
|
178
|
-
>
|
|
179
|
-
{#if empty}{@render empty()}{:else}{t.current.noData}{/if}
|
|
180
|
-
</td>
|
|
215
|
+
{/if}
|
|
216
|
+
</th>
|
|
217
|
+
{/each}
|
|
181
218
|
</tr>
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
<tr
|
|
186
|
-
|
|
187
|
-
|
|
219
|
+
</thead>
|
|
220
|
+
<tbody>
|
|
221
|
+
{#if sorted.length === 0}
|
|
222
|
+
<tr>
|
|
223
|
+
<td
|
|
224
|
+
colspan={columns.length + (selectable ? 1 : 0)}
|
|
225
|
+
class="px-4 py-10 text-center text-sm text-text-muted"
|
|
226
|
+
>
|
|
227
|
+
{#if empty}{@render empty()}{:else}{t.current.noData}{/if}
|
|
228
|
+
</td>
|
|
229
|
+
</tr>
|
|
230
|
+
{:else}
|
|
231
|
+
{#each sorted as row, i (selectable ? keyOf(row) : i)}
|
|
232
|
+
{@const isSelected = selectable && selected.includes(keyOf(row))}
|
|
233
|
+
<tr
|
|
234
|
+
aria-selected={selectable ? isSelected : undefined}
|
|
235
|
+
class="border-b border-hairline last:border-b-0
|
|
188
236
|
{isSelected ? 'bg-brand-light' : striped && i % 2 === 1 ? 'bg-bg-alt' : ''}
|
|
189
237
|
{hoverable ? 'transition-colors duration-150 hover:bg-bg-alt' : ''}"
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
238
|
+
>
|
|
239
|
+
{#if selectable}
|
|
240
|
+
<td class={pad}>
|
|
241
|
+
<Checkbox
|
|
242
|
+
checked={isSelected}
|
|
243
|
+
{tone}
|
|
244
|
+
aria-label={t.current.selectRow}
|
|
245
|
+
onchange={() => toggleRow(row)}
|
|
246
|
+
/>
|
|
247
|
+
</td>
|
|
248
|
+
{/if}
|
|
249
|
+
{#each columns as column (column.key)}
|
|
250
|
+
<td
|
|
251
|
+
class="text-text-secondary {pad} {aligns[column.align ?? 'left']} {column.class ??
|
|
252
|
+
''}"
|
|
253
|
+
>
|
|
254
|
+
{#if cell}
|
|
255
|
+
{@render cell({ row, column, value: row[column.key] })}
|
|
256
|
+
{:else}
|
|
257
|
+
{row[column.key] ?? ''}
|
|
258
|
+
{/if}
|
|
259
|
+
</td>
|
|
260
|
+
{/each}
|
|
261
|
+
</tr>
|
|
262
|
+
{/each}
|
|
263
|
+
{/if}
|
|
264
|
+
</tbody>
|
|
265
|
+
</table>
|
|
266
|
+
</div>
|
|
267
|
+
{#if footer}
|
|
268
|
+
<div
|
|
269
|
+
class="flex flex-wrap items-center gap-3 border-t border-hairline px-4 py-3 font-sans text-[13px] text-text-secondary"
|
|
270
|
+
>
|
|
271
|
+
{@render footer()}
|
|
272
|
+
</div>
|
|
273
|
+
{/if}
|
|
218
274
|
</div>
|
|
@@ -29,6 +29,18 @@ declare function $$render<T extends Record<string, unknown>>(): {
|
|
|
29
29
|
compact?: boolean;
|
|
30
30
|
/** Header stays put while the body scrolls — pair with a `max-h-*` class. */
|
|
31
31
|
stickyHeader?: boolean;
|
|
32
|
+
/** Bar above the table — a title, a search field, a filter row. */
|
|
33
|
+
header?: Snippet;
|
|
34
|
+
/** Bar below the table — pagination, a total, a summary line. */
|
|
35
|
+
footer?: Snippet;
|
|
36
|
+
/**
|
|
37
|
+
* Shown in place of `header` while rows are ticked, after the count and the
|
|
38
|
+
* clear button. Passing it is what turns the bulk bar on.
|
|
39
|
+
*/
|
|
40
|
+
bulkActions?: Snippet<[{
|
|
41
|
+
selected: string[];
|
|
42
|
+
clear: () => void;
|
|
43
|
+
}]>;
|
|
32
44
|
/** Bindable. Set it to sort; leave `sortable` columns to drive it. */
|
|
33
45
|
sort?: TableSort | null;
|
|
34
46
|
/** Sort the rows here rather than refetching them server-side. Default true. */
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
<script lang="ts">
|
|
2
|
+
import type { Snippet } from 'svelte';
|
|
2
3
|
import type { HTMLAttributes } from 'svelte/elements';
|
|
3
4
|
import { edge } from './lift.js';
|
|
4
5
|
import {
|
|
@@ -9,10 +10,13 @@
|
|
|
9
10
|
toneText,
|
|
10
11
|
type Tone
|
|
11
12
|
} from '../../core/tones.js';
|
|
13
|
+
import { iconMd } from './icon.js';
|
|
12
14
|
|
|
13
15
|
export interface TabItem {
|
|
14
16
|
value: string;
|
|
15
17
|
label: string;
|
|
18
|
+
/** Leading icon, 16px. */
|
|
19
|
+
icon?: Snippet;
|
|
16
20
|
disabled?: boolean;
|
|
17
21
|
/** Small count/label rendered after the tab title. */
|
|
18
22
|
badge?: string | number;
|
|
@@ -90,6 +94,7 @@
|
|
|
90
94
|
onclick={() => select(item)}
|
|
91
95
|
class={tabClass(value === item.value)}
|
|
92
96
|
>
|
|
97
|
+
{#if item.icon}<span class={iconMd}>{@render item.icon()}</span>{/if}
|
|
93
98
|
{item.label}
|
|
94
99
|
{#if item.badge !== undefined}
|
|
95
100
|
<span
|
|
@@ -1,8 +1,11 @@
|
|
|
1
|
+
import type { Snippet } from 'svelte';
|
|
1
2
|
import type { HTMLAttributes } from 'svelte/elements';
|
|
2
3
|
import { type Tone } from '../../core/tones.js';
|
|
3
4
|
export interface TabItem {
|
|
4
5
|
value: string;
|
|
5
6
|
label: string;
|
|
7
|
+
/** Leading icon, 16px. */
|
|
8
|
+
icon?: Snippet;
|
|
6
9
|
disabled?: boolean;
|
|
7
10
|
/** Small count/label rendered after the tab title. */
|
|
8
11
|
badge?: string | number;
|
|
@@ -4,6 +4,7 @@
|
|
|
4
4
|
import { portal } from '../../core/actions/dismissable.js';
|
|
5
5
|
import { toast } from '../../core/toast.svelte.js';
|
|
6
6
|
import { toneText } from '../../core/tones.js';
|
|
7
|
+
import { iconMd } from './icon.js';
|
|
7
8
|
import Spinner from './Spinner.svelte';
|
|
8
9
|
import { useLocale } from '../../core/locale.svelte.js';
|
|
9
10
|
import { soft } from './lift.js';
|
|
@@ -62,6 +63,8 @@
|
|
|
62
63
|
<span class="mt-0.5 shrink-0 {toneText[item.tone]}">
|
|
63
64
|
{#if item.loading}
|
|
64
65
|
<Spinner size="sm" label="" />
|
|
66
|
+
{:else if item.icon}
|
|
67
|
+
<span class={iconMd}>{@render item.icon()}</span>
|
|
65
68
|
{:else if item.tone === 'success'}
|
|
66
69
|
<svg class="size-4" viewBox="0 0 16 16" fill="none" aria-hidden="true">
|
|
67
70
|
<circle cx="8" cy="8" r="6.5" stroke="currentColor" stroke-width="1.5" />
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
/*
|
|
2
2
|
* Optional: the two faces sprout is designed around — Fredoka (headings) and
|
|
3
|
-
*
|
|
3
|
+
* Work Sans (body). Import this only if your project doesn't already
|
|
4
4
|
* self-host or load them another way — without it the tokens fall back to the
|
|
5
5
|
* system stack, which works but loses the round, hand-drawn warmth the style is
|
|
6
6
|
* built on.
|
|
@@ -14,7 +14,7 @@
|
|
|
14
14
|
*
|
|
15
15
|
* Four rules for two families: both are variable fonts, so one file per subset
|
|
16
16
|
* covers every weight the style uses — 400 to 600 for Fredoka, 400 to 700 for
|
|
17
|
-
*
|
|
17
|
+
* Work Sans. Latin and Latin Extended only. Add
|
|
18
18
|
* `<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>` to
|
|
19
19
|
* your document head to open the connection earlier.
|
|
20
20
|
*/
|
|
@@ -49,15 +49,14 @@
|
|
|
49
49
|
U+A720-A7FF;
|
|
50
50
|
}
|
|
51
51
|
|
|
52
|
-
/* ---
|
|
52
|
+
/* --- Work Sans --- */
|
|
53
53
|
/* latin */
|
|
54
54
|
@font-face {
|
|
55
|
-
font-family: '
|
|
55
|
+
font-family: 'Work Sans';
|
|
56
56
|
font-style: normal;
|
|
57
57
|
font-weight: 400 700;
|
|
58
58
|
font-display: swap;
|
|
59
|
-
src: url(https://fonts.gstatic.com/s/
|
|
60
|
-
format('woff2');
|
|
59
|
+
src: url(https://fonts.gstatic.com/s/worksans/v24/QGYsz_wNahGAdqQ43Rh_fKDp.woff2) format('woff2');
|
|
61
60
|
unicode-range:
|
|
62
61
|
U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+0304, U+0308, U+0329,
|
|
63
62
|
U+2000-206F, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD;
|
|
@@ -65,11 +64,11 @@
|
|
|
65
64
|
|
|
66
65
|
/* latin-ext */
|
|
67
66
|
@font-face {
|
|
68
|
-
font-family: '
|
|
67
|
+
font-family: 'Work Sans';
|
|
69
68
|
font-style: normal;
|
|
70
69
|
font-weight: 400 700;
|
|
71
70
|
font-display: swap;
|
|
72
|
-
src: url(https://fonts.gstatic.com/s/
|
|
71
|
+
src: url(https://fonts.gstatic.com/s/worksans/v24/QGYsz_wNahGAdqQ43Rh_cqDpp_k.woff2)
|
|
73
72
|
format('woff2');
|
|
74
73
|
unicode-range:
|
|
75
74
|
U+0100-02BA, U+02BD-02C5, U+02C7-02CC, U+02CE-02D7, U+02DD-02FF, U+0304, U+0308, U+0329,
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The box a consumer-supplied icon renders into.
|
|
3
|
+
*
|
|
4
|
+
* Every icon in the library is a `Snippet` the app writes — the package ships
|
|
5
|
+
* no icon set and no runtime dependency — so the component has to size the
|
|
6
|
+
* glyph rather than trust it. The `*:` variant hits the snippet's own element,
|
|
7
|
+
* which is what keeps a bare `<svg viewBox="0 0 16 16">` from laying out at its
|
|
8
|
+
* intrinsic 300×150.
|
|
9
|
+
*
|
|
10
|
+
* Kept per style rather than in `core/`: an app only `@source`s the style
|
|
11
|
+
* folder it installed, so a class string living outside it would never be
|
|
12
|
+
* generated by Tailwind.
|
|
13
|
+
*/
|
|
14
|
+
/** 14px — menu rows, chips, anything sitting on one line of small text. */
|
|
15
|
+
export declare const iconSm = "grid size-3.5 shrink-0 place-items-center *:size-3.5";
|
|
16
|
+
/** 16px — the default: nav items, tabs, buttons, list rows. */
|
|
17
|
+
export declare const iconMd = "grid size-4 shrink-0 place-items-center *:size-4";
|
|
18
|
+
/** 20px — headers, stats, anything sitting beside a heading. */
|
|
19
|
+
export declare const iconLg = "grid size-5 shrink-0 place-items-center *:size-5";
|
|
20
|
+
/** 24px — dialog and empty-state marks. */
|
|
21
|
+
export declare const iconXl = "grid size-6 shrink-0 place-items-center *:size-6";
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The box a consumer-supplied icon renders into.
|
|
3
|
+
*
|
|
4
|
+
* Every icon in the library is a `Snippet` the app writes — the package ships
|
|
5
|
+
* no icon set and no runtime dependency — so the component has to size the
|
|
6
|
+
* glyph rather than trust it. The `*:` variant hits the snippet's own element,
|
|
7
|
+
* which is what keeps a bare `<svg viewBox="0 0 16 16">` from laying out at its
|
|
8
|
+
* intrinsic 300×150.
|
|
9
|
+
*
|
|
10
|
+
* Kept per style rather than in `core/`: an app only `@source`s the style
|
|
11
|
+
* folder it installed, so a class string living outside it would never be
|
|
12
|
+
* generated by Tailwind.
|
|
13
|
+
*/
|
|
14
|
+
/** 14px — menu rows, chips, anything sitting on one line of small text. */
|
|
15
|
+
export const iconSm = 'grid size-3.5 shrink-0 place-items-center *:size-3.5';
|
|
16
|
+
/** 16px — the default: nav items, tabs, buttons, list rows. */
|
|
17
|
+
export const iconMd = 'grid size-4 shrink-0 place-items-center *:size-4';
|
|
18
|
+
/** 20px — headers, stats, anything sitting beside a heading. */
|
|
19
|
+
export const iconLg = 'grid size-5 shrink-0 place-items-center *:size-5';
|
|
20
|
+
/** 24px — dialog and empty-state marks. */
|
|
21
|
+
export const iconXl = 'grid size-6 shrink-0 place-items-center *:size-6';
|
|
@@ -22,8 +22,6 @@ export { default as Switch } from './Switch.svelte';
|
|
|
22
22
|
export type { SwitchSize } from './Switch.svelte';
|
|
23
23
|
export { default as Field } from './Field.svelte';
|
|
24
24
|
export { default as Label } from './Label.svelte';
|
|
25
|
-
export { default as PasswordInput } from './PasswordInput.svelte';
|
|
26
|
-
export { default as NumberInput } from './NumberInput.svelte';
|
|
27
25
|
export { default as Slider } from './Slider.svelte';
|
|
28
26
|
export { default as RadioGroup } from './RadioGroup.svelte';
|
|
29
27
|
export type { RadioOption } from './RadioGroup.svelte';
|
|
@@ -76,7 +74,7 @@ export type { StepItem } from './Steps.svelte';
|
|
|
76
74
|
export { default as Navbar } from './Navbar.svelte';
|
|
77
75
|
export type { NavItem } from './Navbar.svelte';
|
|
78
76
|
export { default as Sidebar } from './Sidebar.svelte';
|
|
79
|
-
export type { SidebarItem, SidebarSection } from './Sidebar.svelte';
|
|
77
|
+
export type { SidebarVariant, SidebarItem, SidebarSection } from './Sidebar.svelte';
|
|
80
78
|
export { default as Footer } from './Footer.svelte';
|
|
81
79
|
export type { FooterLink, FooterColumn } from './Footer.svelte';
|
|
82
80
|
export { default as HeroSection } from './HeroSection.svelte';
|
|
@@ -21,8 +21,6 @@ export { default as Radio } from './Radio.svelte';
|
|
|
21
21
|
export { default as Switch } from './Switch.svelte';
|
|
22
22
|
export { default as Field } from './Field.svelte';
|
|
23
23
|
export { default as Label } from './Label.svelte';
|
|
24
|
-
export { default as PasswordInput } from './PasswordInput.svelte';
|
|
25
|
-
export { default as NumberInput } from './NumberInput.svelte';
|
|
26
24
|
export { default as Slider } from './Slider.svelte';
|
|
27
25
|
export { default as RadioGroup } from './RadioGroup.svelte';
|
|
28
26
|
export { default as CheckboxGroup } from './CheckboxGroup.svelte';
|
|
@@ -102,18 +102,18 @@
|
|
|
102
102
|
/* --- type --- */
|
|
103
103
|
/*
|
|
104
104
|
* Two faces, and the split is the point. Fredoka sets headings: geometric,
|
|
105
|
-
* round-terminalled, drawn wide — the same warmth the shapes have.
|
|
106
|
-
*
|
|
107
|
-
*
|
|
105
|
+
* round-terminalled, drawn wide — the same warmth the shapes have. Work
|
|
106
|
+
* Sans sets everything a reader has to get through, because Fredoka at 15px
|
|
107
|
+
* in a paragraph is charm at the cost of the sentence — and it is the body
|
|
108
|
+
* face in every style, so only the headings change voice when you swap.
|
|
108
109
|
*
|
|
109
110
|
* Both are variable files, one request per subset — see `fonts.css`.
|
|
110
111
|
* Everything degrades to the system stack if that file is not imported, so
|
|
111
112
|
* the webfonts stay optional.
|
|
112
113
|
*/
|
|
113
|
-
--font-sans:
|
|
114
|
-
'Plus Jakarta Sans', ui-sans-serif, system-ui, -apple-system, 'Segoe UI', Roboto, sans-serif;
|
|
114
|
+
--font-sans: 'Work Sans', ui-sans-serif, system-ui, -apple-system, 'Segoe UI', Roboto, sans-serif;
|
|
115
115
|
--font-heading:
|
|
116
|
-
'Fredoka', '
|
|
116
|
+
'Fredoka', 'Work Sans', ui-rounded, ui-sans-serif, system-ui, -apple-system, sans-serif;
|
|
117
117
|
--font-mono: ui-monospace, SFMono-Regular, Menlo, Consolas, 'Liberation Mono', monospace;
|
|
118
118
|
|
|
119
119
|
/* --- motion --- */
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@nqmcreative/ui",
|
|
3
|
-
"version": "0.
|
|
4
|
-
"description": "Svelte 5 + Tailwind CSS v4 component library — three styles (matte, paper, sprout),
|
|
3
|
+
"version": "0.3.0",
|
|
4
|
+
"description": "Svelte 5 + Tailwind CSS v4 component library — three styles (matte, paper, sprout), 63 components each, one shared behaviour core. No runtime dependencies.",
|
|
5
5
|
"scripts": {
|
|
6
6
|
"dev": "vite dev",
|
|
7
7
|
"build": "vite build && svelte-kit sync && svelte-package && node scripts/strip-dist-tests.mjs && node scripts/generate-index.mjs && node scripts/generate-exports.mjs && node scripts/generate-registry.mjs && node scripts/generate-scoped-css.mjs && node scripts/generate-demos.mjs && publint",
|
|
@@ -135,14 +135,6 @@
|
|
|
135
135
|
"types": "./dist/styles/matte/Label.svelte.d.ts",
|
|
136
136
|
"svelte": "./dist/styles/matte/Label.svelte"
|
|
137
137
|
},
|
|
138
|
-
"./matte/password-input": {
|
|
139
|
-
"types": "./dist/styles/matte/PasswordInput.svelte.d.ts",
|
|
140
|
-
"svelte": "./dist/styles/matte/PasswordInput.svelte"
|
|
141
|
-
},
|
|
142
|
-
"./matte/number-input": {
|
|
143
|
-
"types": "./dist/styles/matte/NumberInput.svelte.d.ts",
|
|
144
|
-
"svelte": "./dist/styles/matte/NumberInput.svelte"
|
|
145
|
-
},
|
|
146
138
|
"./matte/slider": {
|
|
147
139
|
"types": "./dist/styles/matte/Slider.svelte.d.ts",
|
|
148
140
|
"svelte": "./dist/styles/matte/Slider.svelte"
|
|
@@ -401,14 +393,6 @@
|
|
|
401
393
|
"types": "./dist/styles/paper/Label.svelte.d.ts",
|
|
402
394
|
"svelte": "./dist/styles/paper/Label.svelte"
|
|
403
395
|
},
|
|
404
|
-
"./paper/password-input": {
|
|
405
|
-
"types": "./dist/styles/paper/PasswordInput.svelte.d.ts",
|
|
406
|
-
"svelte": "./dist/styles/paper/PasswordInput.svelte"
|
|
407
|
-
},
|
|
408
|
-
"./paper/number-input": {
|
|
409
|
-
"types": "./dist/styles/paper/NumberInput.svelte.d.ts",
|
|
410
|
-
"svelte": "./dist/styles/paper/NumberInput.svelte"
|
|
411
|
-
},
|
|
412
396
|
"./paper/slider": {
|
|
413
397
|
"types": "./dist/styles/paper/Slider.svelte.d.ts",
|
|
414
398
|
"svelte": "./dist/styles/paper/Slider.svelte"
|
|
@@ -667,14 +651,6 @@
|
|
|
667
651
|
"types": "./dist/styles/sprout/Label.svelte.d.ts",
|
|
668
652
|
"svelte": "./dist/styles/sprout/Label.svelte"
|
|
669
653
|
},
|
|
670
|
-
"./sprout/password-input": {
|
|
671
|
-
"types": "./dist/styles/sprout/PasswordInput.svelte.d.ts",
|
|
672
|
-
"svelte": "./dist/styles/sprout/PasswordInput.svelte"
|
|
673
|
-
},
|
|
674
|
-
"./sprout/number-input": {
|
|
675
|
-
"types": "./dist/styles/sprout/NumberInput.svelte.d.ts",
|
|
676
|
-
"svelte": "./dist/styles/sprout/NumberInput.svelte"
|
|
677
|
-
},
|
|
678
654
|
"./sprout/slider": {
|
|
679
655
|
"types": "./dist/styles/sprout/Slider.svelte.d.ts",
|
|
680
656
|
"svelte": "./dist/styles/sprout/Slider.svelte"
|
package/registry.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@nqmcreative/ui",
|
|
3
3
|
"homepage": "https://github.com/mukhsamr/nqmcreative-ui",
|
|
4
|
-
"count":
|
|
4
|
+
"count": 63,
|
|
5
5
|
"demoStyle": "matte",
|
|
6
6
|
"styles": [
|
|
7
7
|
{
|
|
@@ -190,40 +190,6 @@
|
|
|
190
190
|
"uses": [],
|
|
191
191
|
"modules": []
|
|
192
192
|
},
|
|
193
|
-
{
|
|
194
|
-
"name": "PasswordInput",
|
|
195
|
-
"slug": "password-input",
|
|
196
|
-
"category": "forms",
|
|
197
|
-
"description": "Password field with a visibility toggle and a strength meter.",
|
|
198
|
-
"subpaths": {
|
|
199
|
-
"matte": "@nqmcreative/ui/matte/password-input",
|
|
200
|
-
"paper": "@nqmcreative/ui/paper/password-input",
|
|
201
|
-
"sprout": "@nqmcreative/ui/sprout/password-input"
|
|
202
|
-
},
|
|
203
|
-
"uses": [],
|
|
204
|
-
"modules": [
|
|
205
|
-
"locale",
|
|
206
|
-
"password",
|
|
207
|
-
"tones"
|
|
208
|
-
]
|
|
209
|
-
},
|
|
210
|
-
{
|
|
211
|
-
"name": "NumberInput",
|
|
212
|
-
"slug": "number-input",
|
|
213
|
-
"category": "forms",
|
|
214
|
-
"description": "Number field with steppers, clamping and decimal handling.",
|
|
215
|
-
"subpaths": {
|
|
216
|
-
"matte": "@nqmcreative/ui/matte/number-input",
|
|
217
|
-
"paper": "@nqmcreative/ui/paper/number-input",
|
|
218
|
-
"sprout": "@nqmcreative/ui/sprout/number-input"
|
|
219
|
-
},
|
|
220
|
-
"uses": [],
|
|
221
|
-
"modules": [
|
|
222
|
-
"locale",
|
|
223
|
-
"number",
|
|
224
|
-
"tones"
|
|
225
|
-
]
|
|
226
|
-
},
|
|
227
193
|
{
|
|
228
194
|
"name": "Slider",
|
|
229
195
|
"slug": "slider",
|
|
@@ -942,7 +908,8 @@
|
|
|
942
908
|
"dialog",
|
|
943
909
|
"list",
|
|
944
910
|
"locale",
|
|
945
|
-
"tones"
|
|
911
|
+
"tones",
|
|
912
|
+
"trigger"
|
|
946
913
|
]
|
|
947
914
|
},
|
|
948
915
|
{
|