runeforge 0.0.4 → 0.0.6
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 +50 -0
- package/dist/components/common/Header.svelte +13 -1
- package/dist/components/crud/views/Create.svelte +7 -1
- package/dist/components/crud/views/List.svelte +9 -1
- package/dist/components/crud/views/Read.svelte +7 -1
- package/dist/components/crud/views/Update.svelte +7 -1
- package/dist/components/navigation/Breadcrumbs.svelte +28 -3
- package/dist/components/table/Paginator.svelte +2 -1
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -20,6 +20,9 @@ A SvelteKit toolkit that forges forms, tables, actions, and CRUD workflows from
|
|
|
20
20
|
- [Requirements](#requirements)
|
|
21
21
|
- [Key Features](#key-features)
|
|
22
22
|
- [Installation](#installation)
|
|
23
|
+
- [Theming](#theming)
|
|
24
|
+
- [Tailwind source scanning](#tailwind-source-scanning)
|
|
25
|
+
- [CSS variables](#css-variables)
|
|
23
26
|
- [Basic Usage](#basic-usage)
|
|
24
27
|
- [1. Define your interface and metadata](#1-define-your-interface-and-metadata)
|
|
25
28
|
- [2. Create the model](#2-create-the-model)
|
|
@@ -86,6 +89,53 @@ pnpm add runeforge
|
|
|
86
89
|
|
|
87
90
|
---
|
|
88
91
|
|
|
92
|
+
## Theming
|
|
93
|
+
|
|
94
|
+
### Tailwind source scanning
|
|
95
|
+
|
|
96
|
+
Runeforge components use Tailwind CSS utility classes internally. Tailwind v4 does not scan `node_modules` by default, so add an `@source` directive in your project's `app.css` to ensure every utility class is generated:
|
|
97
|
+
|
|
98
|
+
```css
|
|
99
|
+
@import "tailwindcss";
|
|
100
|
+
@source "../node_modules/runeforge/dist";
|
|
101
|
+
@plugin "daisyui";
|
|
102
|
+
```
|
|
103
|
+
|
|
104
|
+
### CSS variables
|
|
105
|
+
|
|
106
|
+
Key visual properties are exposed as CSS custom properties so you can tune them per project. Set them on `:root` (or any narrower selector) in your `app.css`:
|
|
107
|
+
|
|
108
|
+
```css
|
|
109
|
+
:root {
|
|
110
|
+
--runeforge-crud-title-size: 1.875rem;
|
|
111
|
+
--runeforge-breadcrumb-font-size: 0.875rem;
|
|
112
|
+
--runeforge-breadcrumb-icon-size: 1rem;
|
|
113
|
+
}
|
|
114
|
+
```
|
|
115
|
+
|
|
116
|
+
Responsive overrides work too:
|
|
117
|
+
|
|
118
|
+
```css
|
|
119
|
+
:root {
|
|
120
|
+
--runeforge-crud-title-size: 1.25rem;
|
|
121
|
+
}
|
|
122
|
+
@media (min-width: 768px) {
|
|
123
|
+
:root {
|
|
124
|
+
--runeforge-crud-title-size: 1.875rem;
|
|
125
|
+
}
|
|
126
|
+
}
|
|
127
|
+
```
|
|
128
|
+
|
|
129
|
+
| Variable | Default | Affects |
|
|
130
|
+
| --- | --- | --- |
|
|
131
|
+
| `--runeforge-crud-max-width` | _(none)_ | Max width of the Header and List view; centers them when set |
|
|
132
|
+
| `--runeforge-form-max-width` | `32rem` | Max width of the form/fields panel in Create, Update, and Read views |
|
|
133
|
+
| `--runeforge-crud-title-size` | `1.875rem` | `<h1>` inside the `Header` component |
|
|
134
|
+
| `--runeforge-breadcrumb-font-size` | `0.875rem` | Breadcrumb label text size |
|
|
135
|
+
| `--runeforge-breadcrumb-icon-size` | `1rem` | Breadcrumb icon width and height |
|
|
136
|
+
|
|
137
|
+
---
|
|
138
|
+
|
|
89
139
|
## Basic Usage
|
|
90
140
|
|
|
91
141
|
### 1. Define your interface and metadata
|
|
@@ -16,7 +16,7 @@
|
|
|
16
16
|
} = $props();
|
|
17
17
|
</script>
|
|
18
18
|
|
|
19
|
-
<div class="flex flex-col gap-4 sm:flex-row sm:items-start sm:justify-between">
|
|
19
|
+
<div class="header-root flex flex-col gap-4 sm:flex-row sm:items-start sm:justify-between">
|
|
20
20
|
<div class="flex flex-col gap-1 flex-1">
|
|
21
21
|
<h1>{title}</h1>
|
|
22
22
|
<Breadcrumbs items={breadcrumbs} {admin} />
|
|
@@ -28,3 +28,15 @@
|
|
|
28
28
|
</div>
|
|
29
29
|
{/if}
|
|
30
30
|
</div>
|
|
31
|
+
|
|
32
|
+
<style>
|
|
33
|
+
h1 {
|
|
34
|
+
font-size: var(--runeforge-crud-title-size, 1.875rem);
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
.header-root {
|
|
38
|
+
width: 100%;
|
|
39
|
+
max-width: var(--runeforge-crud-max-width);
|
|
40
|
+
margin-inline: auto;
|
|
41
|
+
}
|
|
42
|
+
</style>
|
|
@@ -100,7 +100,7 @@
|
|
|
100
100
|
method="POST"
|
|
101
101
|
action={creation.endpoint ?? '?/create'}
|
|
102
102
|
enctype={hasFileField ? 'multipart/form-data' : undefined}
|
|
103
|
-
class="mx-auto flex w-full
|
|
103
|
+
class="mx-auto flex w-full flex-col gap-4 px-4"
|
|
104
104
|
use:enhance={({ formData, cancel }) => {
|
|
105
105
|
fieldErrors = {};
|
|
106
106
|
internalError = '';
|
|
@@ -145,3 +145,9 @@
|
|
|
145
145
|
</div>
|
|
146
146
|
</form>
|
|
147
147
|
</div>
|
|
148
|
+
|
|
149
|
+
<style>
|
|
150
|
+
form {
|
|
151
|
+
max-width: var(--runeforge-form-max-width, 32rem);
|
|
152
|
+
}
|
|
153
|
+
</style>
|
|
@@ -121,7 +121,7 @@
|
|
|
121
121
|
</div>
|
|
122
122
|
{/snippet}
|
|
123
123
|
|
|
124
|
-
<div class="flex flex-col gap-6">
|
|
124
|
+
<div class="list-root flex flex-col gap-6">
|
|
125
125
|
|
|
126
126
|
<Header
|
|
127
127
|
admin
|
|
@@ -168,3 +168,11 @@
|
|
|
168
168
|
rowActions={showRowActions ? actionsCell : undefined}
|
|
169
169
|
/>
|
|
170
170
|
</div>
|
|
171
|
+
|
|
172
|
+
<style>
|
|
173
|
+
.list-root {
|
|
174
|
+
width: 100%;
|
|
175
|
+
max-width: var(--runeforge-crud-max-width);
|
|
176
|
+
margin-inline: auto;
|
|
177
|
+
}
|
|
178
|
+
</style>
|
|
@@ -71,7 +71,7 @@
|
|
|
71
71
|
]}
|
|
72
72
|
/>
|
|
73
73
|
|
|
74
|
-
<div class="mx-auto flex w-full
|
|
74
|
+
<div class="fields-panel mx-auto flex w-full flex-col gap-4 px-4">
|
|
75
75
|
{#each fields as field (field.attribute)}
|
|
76
76
|
<Field {field} {record} readonly />
|
|
77
77
|
{/each}
|
|
@@ -83,3 +83,9 @@
|
|
|
83
83
|
</div>
|
|
84
84
|
</div>
|
|
85
85
|
</div>
|
|
86
|
+
|
|
87
|
+
<style>
|
|
88
|
+
.fields-panel {
|
|
89
|
+
max-width: var(--runeforge-form-max-width, 32rem);
|
|
90
|
+
}
|
|
91
|
+
</style>
|
|
@@ -108,7 +108,7 @@
|
|
|
108
108
|
method="POST"
|
|
109
109
|
action={update.endpoint ?? '?/update'}
|
|
110
110
|
enctype={hasFileField ? 'multipart/form-data' : undefined}
|
|
111
|
-
class="mx-auto flex w-full
|
|
111
|
+
class="mx-auto flex w-full flex-col gap-4 px-4"
|
|
112
112
|
use:enhance={({ formData, cancel }) => {
|
|
113
113
|
fieldErrors = {};
|
|
114
114
|
internalError = '';
|
|
@@ -146,3 +146,9 @@
|
|
|
146
146
|
</div>
|
|
147
147
|
</form>
|
|
148
148
|
</div>
|
|
149
|
+
|
|
150
|
+
<style>
|
|
151
|
+
form {
|
|
152
|
+
max-width: var(--runeforge-form-max-width, 32rem);
|
|
153
|
+
}
|
|
154
|
+
</style>
|
|
@@ -24,7 +24,7 @@
|
|
|
24
24
|
const allItems = $derived([home, ...items]);
|
|
25
25
|
</script>
|
|
26
26
|
|
|
27
|
-
<div class="breadcrumbs
|
|
27
|
+
<div class="breadcrumbs">
|
|
28
28
|
<ul>
|
|
29
29
|
{#each allItems as item, i (i)}
|
|
30
30
|
<li>
|
|
@@ -32,7 +32,7 @@
|
|
|
32
32
|
<a class="inline-flex items-center gap-2" {...item.link}>
|
|
33
33
|
{#if item.icon}
|
|
34
34
|
{@const ItemIcon = item.icon}
|
|
35
|
-
<ItemIcon
|
|
35
|
+
<ItemIcon />
|
|
36
36
|
{/if}
|
|
37
37
|
<span>{item.label}</span>
|
|
38
38
|
</a>
|
|
@@ -40,7 +40,7 @@
|
|
|
40
40
|
<span class="inline-flex items-center gap-2">
|
|
41
41
|
{#if item.icon}
|
|
42
42
|
{@const ItemIcon = item.icon}
|
|
43
|
-
<ItemIcon
|
|
43
|
+
<ItemIcon />
|
|
44
44
|
{/if}
|
|
45
45
|
<span>{item.label}</span>
|
|
46
46
|
</span>
|
|
@@ -51,6 +51,16 @@
|
|
|
51
51
|
</div>
|
|
52
52
|
|
|
53
53
|
<style>
|
|
54
|
+
div {
|
|
55
|
+
font-size: var(--runeforge-breadcrumb-font-size, 0.875rem);
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
:global(.breadcrumbs svg) {
|
|
59
|
+
width: var(--runeforge-breadcrumb-icon-size, 1rem);
|
|
60
|
+
height: var(--runeforge-breadcrumb-icon-size, 1rem);
|
|
61
|
+
flex-shrink: 0;
|
|
62
|
+
}
|
|
63
|
+
|
|
54
64
|
/*
|
|
55
65
|
* DaisyUI breadcrumbs use @layer rules that Tailwind v4 doesn't propagate
|
|
56
66
|
* from node_modules. These unlayered rules override that gap.
|
|
@@ -84,4 +94,19 @@
|
|
|
84
94
|
margin-inline: 0.5rem 0.75rem;
|
|
85
95
|
rotate: 45deg;
|
|
86
96
|
}
|
|
97
|
+
|
|
98
|
+
/*
|
|
99
|
+
* Tailwind preflight sets svg { display: block }, which stacks icons above
|
|
100
|
+
* labels when the <a>/<span> inline-flex class isn't generated from node_modules.
|
|
101
|
+
*/
|
|
102
|
+
:global(.breadcrumbs > ul > li > a),
|
|
103
|
+
:global(.breadcrumbs > ul > li > span),
|
|
104
|
+
:global(.breadcrumbs > ol > li > a),
|
|
105
|
+
:global(.breadcrumbs > ol > li > span),
|
|
106
|
+
:global(.breadcrumbs > menu > li > a),
|
|
107
|
+
:global(.breadcrumbs > menu > li > span) {
|
|
108
|
+
display: inline-flex;
|
|
109
|
+
align-items: center;
|
|
110
|
+
gap: 0.5rem;
|
|
111
|
+
}
|
|
87
112
|
</style>
|
|
@@ -76,7 +76,8 @@
|
|
|
76
76
|
{:else if p === page}
|
|
77
77
|
<input
|
|
78
78
|
type="number"
|
|
79
|
-
class="join-item btn btn-sm
|
|
79
|
+
class="join-item btn btn-sm w-12 text-center appearance-none"
|
|
80
|
+
style="background-color: var(--color-base-100);"
|
|
80
81
|
min="1"
|
|
81
82
|
max={totalPages}
|
|
82
83
|
value={page}
|