@wells-nelson/displays 0.0.0-stage → 1.0.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 +69 -2
- package/dist/AppHeader.svelte +158 -0
- package/dist/AppHeader.svelte.d.ts +26 -0
- package/dist/Badge.svelte +43 -0
- package/dist/Badge.svelte.d.ts +8 -0
- package/dist/Button.svelte +81 -0
- package/dist/Button.svelte.d.ts +12 -0
- package/dist/ConfirmDialog.svelte +48 -0
- package/dist/ConfirmDialog.svelte.d.ts +11 -0
- package/dist/FatalError.svelte +20 -0
- package/dist/FatalError.svelte.d.ts +9 -0
- package/dist/Icon.svelte +29 -0
- package/dist/Icon.svelte.d.ts +9 -0
- package/dist/IconButton.svelte +59 -0
- package/dist/IconButton.svelte.d.ts +13 -0
- package/dist/Leaderboards.svelte +74 -0
- package/dist/Leaderboards.svelte.d.ts +31 -0
- package/dist/Modal.svelte +106 -0
- package/dist/Modal.svelte.d.ts +12 -0
- package/dist/SortableTable.svelte +161 -0
- package/dist/SortableTable.svelte.d.ts +37 -0
- package/dist/Splash.svelte +17 -0
- package/dist/Splash.svelte.d.ts +6 -0
- package/dist/icons.d.ts +36 -0
- package/dist/icons.js +41 -0
- package/dist/index.d.ts +13 -0
- package/dist/index.js +13 -0
- package/dist/palettes/blue.css +32 -0
- package/dist/palettes/green.css +32 -0
- package/dist/theme.css +233 -0
- package/dist/types.d.ts +24 -0
- package/dist/types.js +15 -0
- package/package.json +44 -4
package/dist/theme.css
ADDED
|
@@ -0,0 +1,233 @@
|
|
|
1
|
+
/*
|
|
2
|
+
* Wells Nelson shared theme: design tokens (light + dark), base element styles, page helpers
|
|
3
|
+
* and drag-and-drop styles. Import once from the root layout:
|
|
4
|
+
*
|
|
5
|
+
* import '@wells-nelson/displays/theme.css';
|
|
6
|
+
* import '@wells-nelson/displays/palettes/green.css'; // optional, or override --accent* yourself
|
|
7
|
+
*
|
|
8
|
+
* The default palette is blue. Override any token on :root after this file (and again inside
|
|
9
|
+
* `@media (prefers-color-scheme: dark)` for dark mode). App-only tokens stay
|
|
10
|
+
* in the app's own stylesheet.
|
|
11
|
+
*/
|
|
12
|
+
:root {
|
|
13
|
+
color-scheme: light;
|
|
14
|
+
--bg: #f3f5f8;
|
|
15
|
+
--surface: #ffffff;
|
|
16
|
+
--surface-2: #edf0f4;
|
|
17
|
+
--surface-hover: #e6eaf0;
|
|
18
|
+
--text: #1b1f26;
|
|
19
|
+
--muted: #646c78;
|
|
20
|
+
--border: #dfe3ea;
|
|
21
|
+
--border-strong: #c3c9d3;
|
|
22
|
+
--accent: #1f5fa8;
|
|
23
|
+
--accent-strong: #184c88;
|
|
24
|
+
--accent-text: #1d58a0;
|
|
25
|
+
--accent-soft: #dbe7f6;
|
|
26
|
+
--on-accent: #ffffff;
|
|
27
|
+
--danger: #b3261e;
|
|
28
|
+
--danger-soft: #f9dedc;
|
|
29
|
+
--warning: #8a5a00;
|
|
30
|
+
--warning-soft: #fdf0d5;
|
|
31
|
+
--radius: 0.6rem;
|
|
32
|
+
--radius-lg: 1rem;
|
|
33
|
+
--shadow: 0 1px 2px rgb(0 0 0 / 0.06), 0 1px 3px rgb(0 0 0 / 0.08);
|
|
34
|
+
--shadow-lg: 0 10px 30px rgb(0 0 0 / 0.18);
|
|
35
|
+
--header-h: 3.5rem;
|
|
36
|
+
--header-offset: calc(var(--header-h) + env(safe-area-inset-top, 0px));
|
|
37
|
+
--content-w: 42rem;
|
|
38
|
+
font-family:
|
|
39
|
+
system-ui,
|
|
40
|
+
-apple-system,
|
|
41
|
+
'Segoe UI',
|
|
42
|
+
Roboto,
|
|
43
|
+
sans-serif;
|
|
44
|
+
font-size: 16px;
|
|
45
|
+
line-height: 1.4;
|
|
46
|
+
-webkit-text-size-adjust: 100%;
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
@media (prefers-color-scheme: dark) {
|
|
50
|
+
:root {
|
|
51
|
+
color-scheme: dark;
|
|
52
|
+
--bg: #111418;
|
|
53
|
+
--surface: #1a1e24;
|
|
54
|
+
--surface-2: #21262d;
|
|
55
|
+
--surface-hover: #282e36;
|
|
56
|
+
--text: #e6e9ee;
|
|
57
|
+
--muted: #98a1ad;
|
|
58
|
+
--border: #2a3038;
|
|
59
|
+
--border-strong: #434b56;
|
|
60
|
+
--accent: #4b8ad6;
|
|
61
|
+
--accent-strong: #62a0e8;
|
|
62
|
+
--accent-text: #7fb2ef;
|
|
63
|
+
--accent-soft: #1d2c40;
|
|
64
|
+
--on-accent: #0b1422;
|
|
65
|
+
--danger: #e5534b;
|
|
66
|
+
--danger-soft: #3d1c1a;
|
|
67
|
+
--warning: #e3b341;
|
|
68
|
+
--warning-soft: #3a2f14;
|
|
69
|
+
}
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
*,
|
|
73
|
+
*::before,
|
|
74
|
+
*::after {
|
|
75
|
+
box-sizing: border-box;
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
body {
|
|
79
|
+
margin: 0;
|
|
80
|
+
background: var(--bg);
|
|
81
|
+
color: var(--text);
|
|
82
|
+
min-height: 100dvh;
|
|
83
|
+
-webkit-tap-highlight-color: transparent;
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
a {
|
|
87
|
+
color: var(--accent-text);
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
h1,
|
|
91
|
+
h2,
|
|
92
|
+
h3 {
|
|
93
|
+
line-height: 1.2;
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
input[type='text'],
|
|
97
|
+
input[type='email'],
|
|
98
|
+
input[type='search'],
|
|
99
|
+
input:not([type]) {
|
|
100
|
+
font: inherit;
|
|
101
|
+
color: inherit;
|
|
102
|
+
width: 100%;
|
|
103
|
+
padding: 0.6rem 0.75rem;
|
|
104
|
+
border: 1px solid var(--border-strong);
|
|
105
|
+
border-radius: var(--radius);
|
|
106
|
+
background: var(--surface);
|
|
107
|
+
}
|
|
108
|
+
|
|
109
|
+
input:focus-visible {
|
|
110
|
+
outline: none;
|
|
111
|
+
border-color: var(--accent);
|
|
112
|
+
box-shadow: 0 0 0 3px var(--accent-soft);
|
|
113
|
+
}
|
|
114
|
+
|
|
115
|
+
input[aria-invalid='true'] {
|
|
116
|
+
border-color: var(--danger);
|
|
117
|
+
}
|
|
118
|
+
|
|
119
|
+
button {
|
|
120
|
+
font: inherit;
|
|
121
|
+
color: inherit;
|
|
122
|
+
}
|
|
123
|
+
|
|
124
|
+
.visually-hidden {
|
|
125
|
+
position: absolute !important;
|
|
126
|
+
width: 1px;
|
|
127
|
+
height: 1px;
|
|
128
|
+
overflow: hidden;
|
|
129
|
+
clip: rect(0 0 0 0);
|
|
130
|
+
white-space: nowrap;
|
|
131
|
+
}
|
|
132
|
+
|
|
133
|
+
/* Page scaffolding */
|
|
134
|
+
.page {
|
|
135
|
+
max-width: var(--content-w);
|
|
136
|
+
margin: 0 auto;
|
|
137
|
+
padding: 1rem 1rem 2rem;
|
|
138
|
+
}
|
|
139
|
+
|
|
140
|
+
.page-title {
|
|
141
|
+
display: flex;
|
|
142
|
+
align-items: center;
|
|
143
|
+
gap: 0.5rem;
|
|
144
|
+
margin: 0.25rem 0 1rem;
|
|
145
|
+
font-size: 1.5rem;
|
|
146
|
+
}
|
|
147
|
+
|
|
148
|
+
.stack {
|
|
149
|
+
display: flex;
|
|
150
|
+
flex-direction: column;
|
|
151
|
+
gap: 0.6rem;
|
|
152
|
+
}
|
|
153
|
+
|
|
154
|
+
.card {
|
|
155
|
+
background: var(--surface);
|
|
156
|
+
border: 1px solid var(--border);
|
|
157
|
+
border-radius: var(--radius);
|
|
158
|
+
box-shadow: var(--shadow);
|
|
159
|
+
}
|
|
160
|
+
|
|
161
|
+
.row-card {
|
|
162
|
+
display: flex;
|
|
163
|
+
align-items: center;
|
|
164
|
+
gap: 0.5rem;
|
|
165
|
+
min-height: 3.25rem;
|
|
166
|
+
padding: 0.25rem 0.5rem 0.25rem 1rem;
|
|
167
|
+
}
|
|
168
|
+
|
|
169
|
+
.muted {
|
|
170
|
+
color: var(--muted);
|
|
171
|
+
}
|
|
172
|
+
|
|
173
|
+
.notice {
|
|
174
|
+
display: flex;
|
|
175
|
+
gap: 0.6rem;
|
|
176
|
+
align-items: flex-start;
|
|
177
|
+
padding: 0.75rem 1rem;
|
|
178
|
+
border-radius: var(--radius);
|
|
179
|
+
background: var(--warning-soft);
|
|
180
|
+
color: var(--text);
|
|
181
|
+
}
|
|
182
|
+
|
|
183
|
+
.notice .icon {
|
|
184
|
+
color: var(--warning);
|
|
185
|
+
margin-top: 0.1rem;
|
|
186
|
+
}
|
|
187
|
+
|
|
188
|
+
.empty {
|
|
189
|
+
padding: 1.5rem 1rem;
|
|
190
|
+
text-align: center;
|
|
191
|
+
color: var(--muted);
|
|
192
|
+
}
|
|
193
|
+
|
|
194
|
+
/* Drag and drop */
|
|
195
|
+
.dnd-active,
|
|
196
|
+
.dnd-active * {
|
|
197
|
+
user-select: none !important;
|
|
198
|
+
-webkit-user-select: none !important;
|
|
199
|
+
cursor: grabbing !important;
|
|
200
|
+
}
|
|
201
|
+
|
|
202
|
+
[data-dnd-item] {
|
|
203
|
+
-webkit-touch-callout: none;
|
|
204
|
+
-webkit-user-select: none;
|
|
205
|
+
user-select: none;
|
|
206
|
+
}
|
|
207
|
+
|
|
208
|
+
.dnd-source {
|
|
209
|
+
opacity: 0.35;
|
|
210
|
+
}
|
|
211
|
+
|
|
212
|
+
.dnd-ghost {
|
|
213
|
+
box-shadow: var(--shadow-lg);
|
|
214
|
+
opacity: 0.95;
|
|
215
|
+
border-radius: var(--radius);
|
|
216
|
+
background: var(--surface);
|
|
217
|
+
list-style: none;
|
|
218
|
+
}
|
|
219
|
+
|
|
220
|
+
.dnd-indicator {
|
|
221
|
+
position: fixed;
|
|
222
|
+
height: 4px;
|
|
223
|
+
border-radius: 2px;
|
|
224
|
+
background: var(--accent);
|
|
225
|
+
pointer-events: none;
|
|
226
|
+
z-index: 1001;
|
|
227
|
+
}
|
|
228
|
+
|
|
229
|
+
.dnd-over {
|
|
230
|
+
outline: 2px dashed var(--accent);
|
|
231
|
+
outline-offset: 2px;
|
|
232
|
+
border-radius: var(--radius);
|
|
233
|
+
}
|
package/dist/types.d.ts
ADDED
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
/** A sortable column of `SortableTable`. */
|
|
2
|
+
export interface SortableColumn<T> {
|
|
3
|
+
/** Unique key; also what `sortKey` refers to. */
|
|
4
|
+
key: string;
|
|
5
|
+
/** Short header text, e.g. "PP". */
|
|
6
|
+
title: string;
|
|
7
|
+
/** Full name for the header tooltip, e.g. "Points played". */
|
|
8
|
+
full?: string;
|
|
9
|
+
/** Value to sort by. Rows without a value (null/undefined) always sort last. */
|
|
10
|
+
value: (row: T) => number | null | undefined;
|
|
11
|
+
/** What the cell shows; defaults to `value`, blank when missing. */
|
|
12
|
+
display?: (row: T) => string | number;
|
|
13
|
+
}
|
|
14
|
+
/** One "top N" card of `Leaderboards`. */
|
|
15
|
+
export interface Leaderboard<T> {
|
|
16
|
+
title: string;
|
|
17
|
+
rows: T[];
|
|
18
|
+
value: (row: T) => string | number;
|
|
19
|
+
}
|
|
20
|
+
/**
|
|
21
|
+
* Sort rows by a numeric value; rows without a value go last whichever the direction, and ties
|
|
22
|
+
* fall back to the label so the order is stable.
|
|
23
|
+
*/
|
|
24
|
+
export declare function sortRows<T>(rows: readonly T[], value: (row: T) => number | null | undefined, label: (row: T) => string, descending: boolean): T[];
|
package/dist/types.js
ADDED
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Sort rows by a numeric value; rows without a value go last whichever the direction, and ties
|
|
3
|
+
* fall back to the label so the order is stable.
|
|
4
|
+
*/
|
|
5
|
+
export function sortRows(rows, value, label, descending) {
|
|
6
|
+
return [...rows].sort((a, b) => {
|
|
7
|
+
const av = value(a);
|
|
8
|
+
const bv = value(b);
|
|
9
|
+
if (av == null || bv == null) {
|
|
10
|
+
const diff = (av == null ? 1 : 0) - (bv == null ? 1 : 0);
|
|
11
|
+
return diff || label(a).localeCompare(label(b));
|
|
12
|
+
}
|
|
13
|
+
return (descending ? bv - av : av - bv) || label(a).localeCompare(label(b));
|
|
14
|
+
});
|
|
15
|
+
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,46 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@wells-nelson/displays",
|
|
3
|
-
"version": "
|
|
4
|
-
"
|
|
5
|
-
"
|
|
6
|
-
|
|
3
|
+
"version": "1.0.0",
|
|
4
|
+
"description": "Svelte 5 display components and theme CSS shared by Wells Nelson apps.",
|
|
5
|
+
"license": "MIT",
|
|
6
|
+
"repository": {
|
|
7
|
+
"type": "git",
|
|
8
|
+
"url": "git+https://github.com/bnelson729/wells-nelson-components.git",
|
|
9
|
+
"directory": "src/npm/displays"
|
|
10
|
+
},
|
|
11
|
+
"homepage": "https://github.com/bnelson729/wells-nelson-components/tree/main/src/npm/displays#readme",
|
|
12
|
+
"bugs": {
|
|
13
|
+
"url": "https://github.com/bnelson729/wells-nelson-components/issues"
|
|
14
|
+
},
|
|
15
|
+
"type": "module",
|
|
16
|
+
"svelte": "./dist/index.js",
|
|
17
|
+
"types": "./dist/index.d.ts",
|
|
18
|
+
"exports": {
|
|
19
|
+
".": {
|
|
20
|
+
"types": "./dist/index.d.ts",
|
|
21
|
+
"svelte": "./dist/index.js",
|
|
22
|
+
"default": "./dist/index.js"
|
|
23
|
+
},
|
|
24
|
+
"./theme.css": "./dist/theme.css",
|
|
25
|
+
"./palettes/*": "./dist/palettes/*"
|
|
26
|
+
},
|
|
27
|
+
"files": [
|
|
28
|
+
"dist"
|
|
29
|
+
],
|
|
30
|
+
"sideEffects": [
|
|
31
|
+
"**/*.css"
|
|
32
|
+
],
|
|
33
|
+
"scripts": {
|
|
34
|
+
"build": "svelte-package -i src/lib -o dist",
|
|
35
|
+
"check": "svelte-check --tsconfig ./tsconfig.json --fail-on-warnings",
|
|
36
|
+
"test": "vitest run",
|
|
37
|
+
"lint:package": "publint"
|
|
38
|
+
},
|
|
39
|
+
"peerDependencies": {
|
|
40
|
+
"svelte": "^5.40.0"
|
|
41
|
+
},
|
|
42
|
+
"publishConfig": {
|
|
43
|
+
"access": "public",
|
|
44
|
+
"provenance": true
|
|
45
|
+
}
|
|
46
|
+
}
|