@marianmeres/stuic 3.143.0 → 3.145.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/AGENTS.md +5 -2
- package/API.md +1 -0
- package/README.md +24 -1
- package/dist/components/CommentInput/CommentInput.svelte +1 -0
- package/dist/components/CommentInput/CommentInput.svelte.d.ts +1 -0
- package/dist/components/CommentInput/README.md +11 -1
- package/dist/components/CommentInput/index.css +13 -0
- package/dist/components/Slider/README.md +205 -0
- package/dist/components/Slider/Slider.svelte +521 -0
- package/dist/components/Slider/Slider.svelte.d.ts +104 -0
- package/dist/components/Slider/index.css +337 -0
- package/dist/components/Slider/index.d.ts +1 -0
- package/dist/components/Slider/index.js +1 -0
- package/dist/index.css +4 -1
- package/dist/index.d.ts +1 -1
- package/dist/index.js +6 -1
- package/docs/architecture.md +23 -1
- package/docs/domains/components.md +2 -1
- package/package.json +9 -13
|
@@ -0,0 +1,337 @@
|
|
|
1
|
+
/* ============================================================================
|
|
2
|
+
SLIDER COMPONENT TOKENS
|
|
3
|
+
Override globally: :root { --stuic-slider-fill: var(--color-green-500); }
|
|
4
|
+
Override locally: <Slider style="--stuic-slider-fill: var(--color-green-500);">
|
|
5
|
+
|
|
6
|
+
Sizing (structural, override at any scope — resolved at the element):
|
|
7
|
+
--stuic-slider-thickness cross-axis size (also set by size="sm|md|lg")
|
|
8
|
+
--stuic-slider-length main-axis size (or use a width/height class)
|
|
9
|
+
--stuic-slider-thumb-inset gap between thumb and track edge
|
|
10
|
+
============================================================================ */
|
|
11
|
+
|
|
12
|
+
:root {
|
|
13
|
+
/* Track (pill background) */
|
|
14
|
+
--stuic-slider-track: var(--stuic-color-muted);
|
|
15
|
+
|
|
16
|
+
/* Fill (value indicator) */
|
|
17
|
+
--stuic-slider-fill: var(--stuic-color-primary);
|
|
18
|
+
|
|
19
|
+
/* Thumb */
|
|
20
|
+
--stuic-slider-thumb: var(--color-white);
|
|
21
|
+
--stuic-slider-thumb-foreground: var(--stuic-color-foreground);
|
|
22
|
+
|
|
23
|
+
/* Tick marks (a second, fill-clipped layer keeps them readable over the fill) */
|
|
24
|
+
--stuic-slider-tick: color-mix(in srgb, var(--stuic-color-foreground) 25%, transparent);
|
|
25
|
+
--stuic-slider-tick-on-fill: color-mix(
|
|
26
|
+
in srgb,
|
|
27
|
+
var(--stuic-color-background) 55%,
|
|
28
|
+
transparent
|
|
29
|
+
);
|
|
30
|
+
|
|
31
|
+
/* Focus ring */
|
|
32
|
+
--stuic-slider-ring-width: 4px;
|
|
33
|
+
--stuic-slider-ring-color: var(--stuic-color-ring);
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
@layer components {
|
|
37
|
+
/* ============================================================================
|
|
38
|
+
BASE / ROOT
|
|
39
|
+
============================================================================ */
|
|
40
|
+
|
|
41
|
+
.stuic-slider {
|
|
42
|
+
/* Internal vars (intent may override the fill) */
|
|
43
|
+
--_track: var(--stuic-slider-track);
|
|
44
|
+
--_fill: var(--stuic-slider-fill);
|
|
45
|
+
--_thumb-bg: var(--stuic-slider-thumb);
|
|
46
|
+
--_thumb-fg: var(--stuic-slider-thumb-foreground);
|
|
47
|
+
--_tick: var(--stuic-slider-tick);
|
|
48
|
+
--_tick-on-fill: var(--stuic-slider-tick-on-fill);
|
|
49
|
+
--_tick-size: var(--stuic-slider-tick-size, 4px);
|
|
50
|
+
|
|
51
|
+
/* Structural (fallbacks resolved here so scoped overrides work) */
|
|
52
|
+
--_thickness: var(--stuic-slider-thickness, 2rem);
|
|
53
|
+
--_length: var(--stuic-slider-length, 10rem);
|
|
54
|
+
--_thumb-inset: var(--stuic-slider-thumb-inset, 3px);
|
|
55
|
+
/* Main-axis extent of the fill (percentages resolve against the track,
|
|
56
|
+
which is the containing block of both the fill and the tick layers) */
|
|
57
|
+
--_fill-len: calc(var(--_ratio) * 100%);
|
|
58
|
+
|
|
59
|
+
display: inline-block;
|
|
60
|
+
vertical-align: middle;
|
|
61
|
+
flex-shrink: 0;
|
|
62
|
+
cursor: pointer;
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
/* FUNCTIONAL, not cosmetic — keyed on an attribute the component always emits
|
|
66
|
+
so it survives `unstyled`: `touch-action: none` keeps the browser from
|
|
67
|
+
stealing touch drags for scrolling, `position: relative` anchors the
|
|
68
|
+
absolutely-positioned track/thumb/hidden input. Attribute specificity (0,1,0)
|
|
69
|
+
leaves it overridable by a consumer utility class (Tailwind's utilities layer
|
|
70
|
+
beats this components layer). */
|
|
71
|
+
[data-stuic-slider] {
|
|
72
|
+
position: relative;
|
|
73
|
+
touch-action: none;
|
|
74
|
+
user-select: none;
|
|
75
|
+
-webkit-user-select: none;
|
|
76
|
+
-webkit-tap-highlight-color: transparent;
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
.stuic-slider[data-size="sm"] {
|
|
80
|
+
--_thickness: var(--stuic-slider-thickness, 1.25rem);
|
|
81
|
+
}
|
|
82
|
+
/* md is the base default (2rem) */
|
|
83
|
+
.stuic-slider[data-size="lg"] {
|
|
84
|
+
--_thickness: var(--stuic-slider-thickness, 3rem);
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
.stuic-slider[data-orientation="horizontal"] {
|
|
88
|
+
width: var(--_length);
|
|
89
|
+
height: var(--_thickness);
|
|
90
|
+
}
|
|
91
|
+
.stuic-slider[data-orientation="vertical"] {
|
|
92
|
+
width: var(--_thickness);
|
|
93
|
+
height: var(--_length);
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
/* Disabled */
|
|
97
|
+
.stuic-slider[data-disabled="true"] {
|
|
98
|
+
cursor: not-allowed;
|
|
99
|
+
opacity: 0.6;
|
|
100
|
+
}
|
|
101
|
+
|
|
102
|
+
/* ============================================================================
|
|
103
|
+
TRACK + FILL
|
|
104
|
+
============================================================================ */
|
|
105
|
+
|
|
106
|
+
.stuic-slider > .track {
|
|
107
|
+
position: absolute;
|
|
108
|
+
inset: 0;
|
|
109
|
+
overflow: hidden;
|
|
110
|
+
border-radius: var(--stuic-slider-radius, 9999px);
|
|
111
|
+
background: var(--_track);
|
|
112
|
+
transition: box-shadow var(--stuic-slider-transition, var(--stuic-transition));
|
|
113
|
+
}
|
|
114
|
+
|
|
115
|
+
.stuic-slider .fill {
|
|
116
|
+
position: absolute;
|
|
117
|
+
background: var(--_fill);
|
|
118
|
+
}
|
|
119
|
+
/* With a value-tracking thumb, the fill reaches the far edge of the thumb */
|
|
120
|
+
.stuic-slider[data-thumb-travels="true"] {
|
|
121
|
+
--_fill-len: calc(var(--_ratio) * (100% - var(--_thickness)) + var(--_thickness));
|
|
122
|
+
}
|
|
123
|
+
.stuic-slider[data-orientation="horizontal"] .fill {
|
|
124
|
+
inset-block: 0;
|
|
125
|
+
inset-inline-start: 0;
|
|
126
|
+
width: var(--_fill-len);
|
|
127
|
+
}
|
|
128
|
+
.stuic-slider[data-orientation="vertical"] .fill {
|
|
129
|
+
inset-inline: 0;
|
|
130
|
+
bottom: 0;
|
|
131
|
+
height: var(--_fill-len);
|
|
132
|
+
}
|
|
133
|
+
|
|
134
|
+
/* Rounded leading edge ("pill inside a pill") */
|
|
135
|
+
.stuic-slider[data-fill-rounded="true"] .fill {
|
|
136
|
+
border-radius: var(--stuic-slider-fill-radius, var(--stuic-slider-radius, 9999px));
|
|
137
|
+
}
|
|
138
|
+
|
|
139
|
+
/* ============================================================================
|
|
140
|
+
THUMB
|
|
141
|
+
============================================================================ */
|
|
142
|
+
|
|
143
|
+
.stuic-slider > .thumb {
|
|
144
|
+
position: absolute;
|
|
145
|
+
display: flex;
|
|
146
|
+
align-items: center;
|
|
147
|
+
justify-content: center;
|
|
148
|
+
width: calc(var(--_thickness) - 2 * var(--_thumb-inset));
|
|
149
|
+
height: calc(var(--_thickness) - 2 * var(--_thumb-inset));
|
|
150
|
+
border-radius: var(--stuic-slider-thumb-radius, 9999px);
|
|
151
|
+
background: var(--_thumb-bg);
|
|
152
|
+
color: var(--_thumb-fg);
|
|
153
|
+
box-shadow: var(--stuic-slider-thumb-shadow, var(--stuic-shadow));
|
|
154
|
+
/* No pointer-events rules needed: the full-size hidden input is the last
|
|
155
|
+
child and always the topmost hit target, so the thumb never receives
|
|
156
|
+
pointer events. Grab detection is geometric, in _onpointerdown. */
|
|
157
|
+
}
|
|
158
|
+
.stuic-slider[data-orientation="horizontal"] > .thumb {
|
|
159
|
+
inset-block-start: var(--_thumb-inset);
|
|
160
|
+
inset-inline-start: var(--_thumb-inset);
|
|
161
|
+
}
|
|
162
|
+
.stuic-slider[data-orientation="vertical"] > .thumb {
|
|
163
|
+
inset-inline-start: var(--_thumb-inset);
|
|
164
|
+
bottom: var(--_thumb-inset);
|
|
165
|
+
}
|
|
166
|
+
/* thumbPosition="value": ride the fill edge (default). thumbPosition="start"
|
|
167
|
+
keeps the offsets above, so only the bar moves (iOS volume look). */
|
|
168
|
+
.stuic-slider[data-thumb-travels="true"][data-orientation="horizontal"] > .thumb {
|
|
169
|
+
inset-inline-start: calc(
|
|
170
|
+
var(--_thumb-inset) + (100% - var(--_thickness)) * var(--_ratio)
|
|
171
|
+
);
|
|
172
|
+
}
|
|
173
|
+
.stuic-slider[data-thumb-travels="true"][data-orientation="vertical"] > .thumb {
|
|
174
|
+
bottom: calc(var(--_thumb-inset) + (100% - var(--_thickness)) * var(--_ratio));
|
|
175
|
+
}
|
|
176
|
+
/* Smooth value movement (keyboard steps); instant while dragging */
|
|
177
|
+
.stuic-slider .fill,
|
|
178
|
+
.stuic-slider > .thumb,
|
|
179
|
+
.stuic-slider > .value {
|
|
180
|
+
transition:
|
|
181
|
+
width var(--stuic-slider-transition, var(--stuic-transition)),
|
|
182
|
+
height var(--stuic-slider-transition, var(--stuic-transition)),
|
|
183
|
+
inset-inline-start var(--stuic-slider-transition, var(--stuic-transition)),
|
|
184
|
+
bottom var(--stuic-slider-transition, var(--stuic-transition));
|
|
185
|
+
}
|
|
186
|
+
.stuic-slider[data-dragging="true"] .fill,
|
|
187
|
+
.stuic-slider[data-dragging="true"] > .thumb,
|
|
188
|
+
.stuic-slider[data-dragging="true"] > .value {
|
|
189
|
+
transition: none;
|
|
190
|
+
}
|
|
191
|
+
|
|
192
|
+
/* ============================================================================
|
|
193
|
+
TICKS
|
|
194
|
+
============================================================================ */
|
|
195
|
+
|
|
196
|
+
/* Two identical tick layers clipped to complementary halves of the track: the
|
|
197
|
+
base one covers the unfilled part, the `on-fill` one the filled part, each
|
|
198
|
+
with its own color. A single layer would vanish into whichever it overlaps,
|
|
199
|
+
and overlapping layers would composite (both tick colors are translucent). */
|
|
200
|
+
.stuic-slider .ticks {
|
|
201
|
+
position: absolute;
|
|
202
|
+
inset: 0;
|
|
203
|
+
transition: clip-path var(--stuic-slider-transition, var(--stuic-transition));
|
|
204
|
+
}
|
|
205
|
+
.stuic-slider[data-dragging="true"] .ticks {
|
|
206
|
+
transition: none;
|
|
207
|
+
}
|
|
208
|
+
.stuic-slider .ticks[data-on-fill="true"] .tick {
|
|
209
|
+
background: var(--_tick-on-fill);
|
|
210
|
+
}
|
|
211
|
+
.stuic-slider[data-orientation="horizontal"] .ticks {
|
|
212
|
+
clip-path: inset(0 0 0 var(--_fill-len));
|
|
213
|
+
}
|
|
214
|
+
.stuic-slider[data-orientation="horizontal"] .ticks[data-on-fill="true"] {
|
|
215
|
+
clip-path: inset(0 calc(100% - var(--_fill-len)) 0 0);
|
|
216
|
+
}
|
|
217
|
+
.stuic-slider[data-orientation="horizontal"]:dir(rtl) .ticks {
|
|
218
|
+
clip-path: inset(0 var(--_fill-len) 0 0);
|
|
219
|
+
}
|
|
220
|
+
.stuic-slider[data-orientation="horizontal"]:dir(rtl) .ticks[data-on-fill="true"] {
|
|
221
|
+
clip-path: inset(0 0 0 calc(100% - var(--_fill-len)));
|
|
222
|
+
}
|
|
223
|
+
.stuic-slider[data-orientation="vertical"] .ticks {
|
|
224
|
+
clip-path: inset(0 0 var(--_fill-len) 0);
|
|
225
|
+
}
|
|
226
|
+
.stuic-slider[data-orientation="vertical"] .ticks[data-on-fill="true"] {
|
|
227
|
+
clip-path: inset(calc(100% - var(--_fill-len)) 0 0 0);
|
|
228
|
+
}
|
|
229
|
+
|
|
230
|
+
.stuic-slider .tick {
|
|
231
|
+
position: absolute;
|
|
232
|
+
width: var(--_tick-size);
|
|
233
|
+
height: var(--_tick-size);
|
|
234
|
+
border-radius: 9999px;
|
|
235
|
+
background: var(--_tick);
|
|
236
|
+
}
|
|
237
|
+
/* Without a traveling thumb there is no thickness inset to hide behind, so the
|
|
238
|
+
travel is inset by half a tick — otherwise the ticks at ratio 0 and 1 sit
|
|
239
|
+
centered on the track edges and the overflow:hidden track halves them. */
|
|
240
|
+
.stuic-slider[data-orientation="horizontal"] .tick {
|
|
241
|
+
top: 50%;
|
|
242
|
+
inset-inline-start: calc(
|
|
243
|
+
var(--_tick-size) / 2 + (100% - var(--_tick-size)) * var(--_tick-ratio)
|
|
244
|
+
);
|
|
245
|
+
transform: translate(-50%, -50%);
|
|
246
|
+
}
|
|
247
|
+
.stuic-slider[data-orientation="vertical"] .tick {
|
|
248
|
+
left: 50%;
|
|
249
|
+
bottom: calc(var(--_tick-size) / 2 + (100% - var(--_tick-size)) * var(--_tick-ratio));
|
|
250
|
+
transform: translate(-50%, 50%);
|
|
251
|
+
}
|
|
252
|
+
/* With a value-tracking thumb, ticks align to the thumb-center travel */
|
|
253
|
+
.stuic-slider[data-thumb-travels="true"][data-orientation="horizontal"] .tick {
|
|
254
|
+
inset-inline-start: calc(
|
|
255
|
+
var(--_thickness) / 2 + (100% - var(--_thickness)) * var(--_tick-ratio)
|
|
256
|
+
);
|
|
257
|
+
}
|
|
258
|
+
.stuic-slider[data-thumb-travels="true"][data-orientation="vertical"] .tick {
|
|
259
|
+
bottom: calc(var(--_thickness) / 2 + (100% - var(--_thickness)) * var(--_tick-ratio));
|
|
260
|
+
}
|
|
261
|
+
/* Logical-property positioning + physical translate: flip centering in RTL */
|
|
262
|
+
.stuic-slider[data-orientation="horizontal"]:dir(rtl) .tick {
|
|
263
|
+
transform: translate(50%, -50%);
|
|
264
|
+
}
|
|
265
|
+
|
|
266
|
+
/* ============================================================================
|
|
267
|
+
VALUE LABEL
|
|
268
|
+
============================================================================ */
|
|
269
|
+
|
|
270
|
+
.stuic-slider > .value {
|
|
271
|
+
position: absolute;
|
|
272
|
+
pointer-events: none;
|
|
273
|
+
white-space: nowrap;
|
|
274
|
+
font-size: var(--text-xs);
|
|
275
|
+
color: var(--stuic-color-muted-foreground);
|
|
276
|
+
}
|
|
277
|
+
.stuic-slider[data-orientation="horizontal"] > .value {
|
|
278
|
+
bottom: calc(100% + var(--stuic-slider-value-gap, 0.375rem));
|
|
279
|
+
inset-inline-start: calc(var(--_ratio) * 100%);
|
|
280
|
+
transform: translateX(-50%);
|
|
281
|
+
}
|
|
282
|
+
.stuic-slider[data-orientation="vertical"] > .value {
|
|
283
|
+
inset-inline-start: calc(100% + var(--stuic-slider-value-gap, 0.375rem));
|
|
284
|
+
bottom: calc(var(--_ratio) * 100%);
|
|
285
|
+
transform: translateY(50%);
|
|
286
|
+
}
|
|
287
|
+
.stuic-slider[data-thumb-travels="true"][data-orientation="horizontal"] > .value {
|
|
288
|
+
inset-inline-start: calc(
|
|
289
|
+
var(--_thickness) / 2 + (100% - var(--_thickness)) * var(--_ratio)
|
|
290
|
+
);
|
|
291
|
+
}
|
|
292
|
+
.stuic-slider[data-thumb-travels="true"][data-orientation="vertical"] > .value {
|
|
293
|
+
bottom: calc(var(--_thickness) / 2 + (100% - var(--_thickness)) * var(--_ratio));
|
|
294
|
+
}
|
|
295
|
+
.stuic-slider[data-orientation="horizontal"]:dir(rtl) > .value {
|
|
296
|
+
transform: translateX(50%);
|
|
297
|
+
}
|
|
298
|
+
|
|
299
|
+
/* The full-size hidden input is the topmost hit target */
|
|
300
|
+
.stuic-slider > input {
|
|
301
|
+
cursor: inherit;
|
|
302
|
+
}
|
|
303
|
+
|
|
304
|
+
/* ============================================================================
|
|
305
|
+
FOCUS RING (keyboard-initiated focus; data-ring is set by the component —
|
|
306
|
+
:focus-visible is unreliable for pointer-initiated programmatic focus)
|
|
307
|
+
============================================================================ */
|
|
308
|
+
|
|
309
|
+
.stuic-slider[data-ring="true"] > .track {
|
|
310
|
+
box-shadow: 0 0 0 var(--stuic-slider-ring-width)
|
|
311
|
+
color-mix(
|
|
312
|
+
in srgb,
|
|
313
|
+
var(--stuic-slider-ring-color) 30%,
|
|
314
|
+
var(--stuic-color-background)
|
|
315
|
+
);
|
|
316
|
+
}
|
|
317
|
+
|
|
318
|
+
/* ============================================================================
|
|
319
|
+
INTENT COLOR MAPPING
|
|
320
|
+
============================================================================ */
|
|
321
|
+
|
|
322
|
+
.stuic-slider[data-intent="primary"] {
|
|
323
|
+
--_fill: var(--stuic-color-primary);
|
|
324
|
+
}
|
|
325
|
+
.stuic-slider[data-intent="accent"] {
|
|
326
|
+
--_fill: var(--stuic-color-accent);
|
|
327
|
+
}
|
|
328
|
+
.stuic-slider[data-intent="success"] {
|
|
329
|
+
--_fill: var(--stuic-color-success);
|
|
330
|
+
}
|
|
331
|
+
.stuic-slider[data-intent="warning"] {
|
|
332
|
+
--_fill: var(--stuic-color-warning);
|
|
333
|
+
}
|
|
334
|
+
.stuic-slider[data-intent="destructive"] {
|
|
335
|
+
--_fill: var(--stuic-color-destructive);
|
|
336
|
+
}
|
|
337
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export { default as Slider, type Props as SliderProps, type SliderIntent, type SliderOrientation, type SliderThumbPosition, type SliderRenderCtx, } from "./Slider.svelte";
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export { default as Slider, } from "./Slider.svelte";
|
package/dist/index.css
CHANGED
|
@@ -71,7 +71,9 @@ In practice:
|
|
|
71
71
|
@import "./components/LoginOrRegisterForm/index.css";
|
|
72
72
|
@import "./components/Checkout/index.css";
|
|
73
73
|
@import "./components/CommandMenu/index.css";
|
|
74
|
-
|
|
74
|
+
/* NOTE: CommentInput/index.css is deliberately NOT imported here — same reason as
|
|
75
|
+
MarkdownEditor's. It is a subpath-export component and imports its own CSS
|
|
76
|
+
locally (see components/CommentInput/index.css). Do not re-add. */
|
|
75
77
|
@import "./components/ContactUsForm/index.css";
|
|
76
78
|
@import "./components/CronInput/index.css";
|
|
77
79
|
@import "./components/DataTable/index.css";
|
|
@@ -96,6 +98,7 @@ In practice:
|
|
|
96
98
|
@import "./components/Progress/index.css";
|
|
97
99
|
@import "./components/Separator/index.css";
|
|
98
100
|
@import "./components/Skeleton/index.css";
|
|
101
|
+
@import "./components/Slider/index.css";
|
|
99
102
|
@import "./components/Spinner/index.css";
|
|
100
103
|
@import "./components/Switch/index.css";
|
|
101
104
|
@import "./components/TabbedMenu/index.css";
|
package/dist/index.d.ts
CHANGED
|
@@ -38,7 +38,6 @@ export * from "./components/Checkout/index.js";
|
|
|
38
38
|
export * from "./components/Collapsible/index.js";
|
|
39
39
|
export * from "./components/ColorScheme/index.js";
|
|
40
40
|
export * from "./components/CommandMenu/index.js";
|
|
41
|
-
export * from "./components/CommentInput/index.js";
|
|
42
41
|
export * from "./components/ContactUsForm/index.js";
|
|
43
42
|
export * from "./components/CronInput/index.js";
|
|
44
43
|
export * from "./components/DataTable/index.js";
|
|
@@ -68,6 +67,7 @@ export * from "./components/PricingTable/index.js";
|
|
|
68
67
|
export * from "./components/Progress/index.js";
|
|
69
68
|
export * from "./components/Separator/index.js";
|
|
70
69
|
export * from "./components/Skeleton/index.js";
|
|
70
|
+
export * from "./components/Slider/index.js";
|
|
71
71
|
export * from "./components/SlidingPanels/index.js";
|
|
72
72
|
export * from "./components/Spinner/index.js";
|
|
73
73
|
export * from "./components/Switch/index.js";
|
package/dist/index.js
CHANGED
|
@@ -39,7 +39,11 @@ export * from "./components/Checkout/index.js";
|
|
|
39
39
|
export * from "./components/Collapsible/index.js";
|
|
40
40
|
export * from "./components/ColorScheme/index.js";
|
|
41
41
|
export * from "./components/CommandMenu/index.js";
|
|
42
|
-
|
|
42
|
+
// NOTE: CommentInput is deliberately NOT exported here. It embeds MarkdownEditor,
|
|
43
|
+
// whose optional @milkdown/* + @codemirror/* peers would then be pulled into the
|
|
44
|
+
// root entry graph of every consumer. It ships as the `@marianmeres/stuic/comment-input`
|
|
45
|
+
// subpath export instead, mirroring `@marianmeres/stuic/markdown-editor`.
|
|
46
|
+
// Guarded by src/lib/barrel-optional-peers.test.ts — do not re-add.
|
|
43
47
|
export * from "./components/ContactUsForm/index.js";
|
|
44
48
|
export * from "./components/CronInput/index.js";
|
|
45
49
|
export * from "./components/DataTable/index.js";
|
|
@@ -69,6 +73,7 @@ export * from "./components/PricingTable/index.js";
|
|
|
69
73
|
export * from "./components/Progress/index.js";
|
|
70
74
|
export * from "./components/Separator/index.js";
|
|
71
75
|
export * from "./components/Skeleton/index.js";
|
|
76
|
+
export * from "./components/Slider/index.js";
|
|
72
77
|
export * from "./components/SlidingPanels/index.js";
|
|
73
78
|
export * from "./components/Spinner/index.js";
|
|
74
79
|
export * from "./components/Switch/index.js";
|
package/docs/architecture.md
CHANGED
|
@@ -80,6 +80,17 @@ src/lib/
|
|
|
80
80
|
|
|
81
81
|
**DO NOT** use `import './index.css'` inside component `.svelte` files.
|
|
82
82
|
|
|
83
|
+
**Exception — subpath-export components.** A component whose peer dependencies are
|
|
84
|
+
declared _optional_ (`MarkdownEditor`, `CommentInput`) is kept off the root barrel and
|
|
85
|
+
shipped behind its own subpath export, so those peers never enter the entry graph of
|
|
86
|
+
consumers who don't use it. Such a component imports its own `index.css` locally and is
|
|
87
|
+
**not** `@import`-ed into `src/lib/index.css` — centralizing it would ship the styles to
|
|
88
|
+
every consumer, defeating the isolation. `sideEffects: ["**/*.css"]` in `package.json`
|
|
89
|
+
keeps the local import alive for real users.
|
|
90
|
+
|
|
91
|
+
Both halves are enforced by `src/lib/barrel-optional-peers.test.ts` — adding such a
|
|
92
|
+
component to the barrel (or its CSS to the central stylesheet) fails the suite.
|
|
93
|
+
|
|
83
94
|
---
|
|
84
95
|
|
|
85
96
|
## Data Flow
|
|
@@ -151,9 +162,20 @@ Theme CSS files are provided by the `@marianmeres/design-tokens` package (a regu
|
|
|
151
162
|
### Package Exports
|
|
152
163
|
|
|
153
164
|
```json
|
|
154
|
-
".":
|
|
165
|
+
".": Main entry (components, utils, actions, icons, theme types)
|
|
166
|
+
"./utils": Utilities only
|
|
167
|
+
"./phone-validation": Phone validation helpers
|
|
168
|
+
"./markdown-editor": MarkdownEditor — optional peer deps, local CSS
|
|
169
|
+
"./comment-input": CommentInput — optional peer deps, local CSS
|
|
155
170
|
```
|
|
156
171
|
|
|
172
|
+
The last two are deliberately **off** the main entry: they reach `@milkdown/*` and
|
|
173
|
+
`@codemirror/*`, which are optional peers. A consumer that has not installed those
|
|
174
|
+
peers gets a hard bundler error (rolldown reports every named import from the
|
|
175
|
+
unresolved stub as `MISSING_EXPORT`) if the root barrel can reach them — even though
|
|
176
|
+
the editor backends sit behind `await import()`, because the specifiers are static
|
|
177
|
+
literals that a bundler must still resolve at build time.
|
|
178
|
+
|
|
157
179
|
---
|
|
158
180
|
|
|
159
181
|
## Security Boundaries
|
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
|
|
3
3
|
## Overview
|
|
4
4
|
|
|
5
|
-
|
|
5
|
+
63 Svelte 5 component directories with consistent API patterns. All use runes-based reactivity.
|
|
6
6
|
|
|
7
7
|
## Component Categories
|
|
8
8
|
|
|
@@ -29,6 +29,7 @@
|
|
|
29
29
|
| Button | Actions with intent/variant/size |
|
|
30
30
|
| ButtonGroupRadio | Toggle group (single selection) |
|
|
31
31
|
| Switch | Boolean toggle |
|
|
32
|
+
| Slider | Fancy range input (fill + optional thumb) |
|
|
32
33
|
| TwCheck | Styled checkbox/radio |
|
|
33
34
|
| DropdownMenu | Popover menu |
|
|
34
35
|
| CommandMenu | Command palette (keyboard-driven) |
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@marianmeres/stuic",
|
|
3
|
-
"version": "3.
|
|
3
|
+
"version": "3.145.0",
|
|
4
4
|
"packageManager": "pnpm@11.5.0",
|
|
5
5
|
"scripts": {
|
|
6
6
|
"dev": "vite dev",
|
|
@@ -19,8 +19,9 @@
|
|
|
19
19
|
"test:ui": "vitest --ui",
|
|
20
20
|
"svelte-check": "svelte-check",
|
|
21
21
|
"svelte-package": "svelte-package",
|
|
22
|
-
"rp": "pnpm run build &&
|
|
23
|
-
"rpm": "pnpm run build &&
|
|
22
|
+
"rp": "pnpm run build && deno run -A jsr:@marianmeres/release patch --no-push && npm publish --access public && git push --follow-tags",
|
|
23
|
+
"rpm": "pnpm run build && deno run -A jsr:@marianmeres/release minor --no-push && npm publish --access public && git push --follow-tags",
|
|
24
|
+
"release": "deno run -A jsr:@marianmeres/release"
|
|
24
25
|
},
|
|
25
26
|
"files": [
|
|
26
27
|
"dist",
|
|
@@ -54,6 +55,11 @@
|
|
|
54
55
|
"types": "./dist/components/MarkdownEditor/index.d.ts",
|
|
55
56
|
"svelte": "./dist/components/MarkdownEditor/index.js",
|
|
56
57
|
"default": "./dist/components/MarkdownEditor/index.js"
|
|
58
|
+
},
|
|
59
|
+
"./comment-input": {
|
|
60
|
+
"types": "./dist/components/CommentInput/index.d.ts",
|
|
61
|
+
"svelte": "./dist/components/CommentInput/index.js",
|
|
62
|
+
"default": "./dist/components/CommentInput/index.js"
|
|
57
63
|
}
|
|
58
64
|
},
|
|
59
65
|
"peerDependencies": {
|
|
@@ -72,8 +78,6 @@
|
|
|
72
78
|
"@milkdown/prose": "^7.0.0",
|
|
73
79
|
"@milkdown/transformer": "^7.0.0",
|
|
74
80
|
"@milkdown/utils": "^7.0.0",
|
|
75
|
-
"dompurify": "^3.0.0",
|
|
76
|
-
"marked": "^18.0.0",
|
|
77
81
|
"svelte": "^5.0.0"
|
|
78
82
|
},
|
|
79
83
|
"peerDependenciesMeta": {
|
|
@@ -121,12 +125,6 @@
|
|
|
121
125
|
},
|
|
122
126
|
"@milkdown/utils": {
|
|
123
127
|
"optional": true
|
|
124
|
-
},
|
|
125
|
-
"dompurify": {
|
|
126
|
-
"optional": true
|
|
127
|
-
},
|
|
128
|
-
"marked": {
|
|
129
|
-
"optional": true
|
|
130
128
|
}
|
|
131
129
|
},
|
|
132
130
|
"devDependencies": {
|
|
@@ -157,11 +155,9 @@
|
|
|
157
155
|
"@tailwindcss/vite": "^4.3.1",
|
|
158
156
|
"@types/node": "^25.9.4",
|
|
159
157
|
"@vitest/browser-playwright": "^4.1.9",
|
|
160
|
-
"dompurify": "^3.4.11",
|
|
161
158
|
"dotenv": "^16.6.1",
|
|
162
159
|
"eslint": "^9.39.4",
|
|
163
160
|
"globals": "^16.5.0",
|
|
164
|
-
"marked": "^18.0.5",
|
|
165
161
|
"playwright": "^1.61.1",
|
|
166
162
|
"prettier": "^3.9.0",
|
|
167
163
|
"prettier-plugin-svelte": "^3.5.2",
|