@vertebr/react 0.2.0 → 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/dist/components/admin/VertebrAdmin.d.ts.map +1 -1
- package/dist/components/admin/VertebrAdmin.js +25 -3
- package/dist/components/config/ConfigForm.d.ts +2 -18
- package/dist/components/config/ConfigForm.d.ts.map +1 -1
- package/dist/components/config/ConfigForm.js +1 -281
- package/dist/components/config/DescriptionInput.d.ts +18 -0
- package/dist/components/config/DescriptionInput.d.ts.map +1 -0
- package/dist/components/config/DescriptionInput.js +152 -0
- package/dist/components/config/ImagePickerModal.d.ts +18 -0
- package/dist/components/config/ImagePickerModal.d.ts.map +1 -0
- package/dist/components/config/ImagePickerModal.js +120 -0
- package/dist/components/config/PriceInput.d.ts +12 -0
- package/dist/components/config/PriceInput.d.ts.map +1 -0
- package/dist/components/config/PriceInput.js +20 -0
- package/dist/components/config/form/ConfigField.d.ts +21 -0
- package/dist/components/config/form/ConfigField.d.ts.map +1 -0
- package/dist/components/config/form/ConfigField.js +48 -0
- package/dist/components/config/form/ConfigForm.d.ts +4 -0
- package/dist/components/config/form/ConfigForm.d.ts.map +1 -0
- package/dist/components/config/form/ConfigForm.js +70 -0
- package/dist/components/config/form/ConfigFormActions.d.ts +10 -0
- package/dist/components/config/form/ConfigFormActions.d.ts.map +1 -0
- package/dist/components/config/form/ConfigFormActions.js +4 -0
- package/dist/components/config/form/RecordConfigForm.d.ts +21 -0
- package/dist/components/config/form/RecordConfigForm.d.ts.map +1 -0
- package/dist/components/config/form/RecordConfigForm.js +37 -0
- package/dist/components/config/form/SettingsConfigForm.d.ts +21 -0
- package/dist/components/config/form/SettingsConfigForm.d.ts.map +1 -0
- package/dist/components/config/form/SettingsConfigForm.js +7 -0
- package/dist/components/config/form/helpers.d.ts +16 -0
- package/dist/components/config/form/helpers.d.ts.map +1 -0
- package/dist/components/config/form/helpers.js +186 -0
- package/dist/components/config/form/types.d.ts +27 -0
- package/dist/components/config/form/types.d.ts.map +1 -0
- package/dist/components/config/form/types.js +1 -0
- package/dist/components/resources/ResourceCell.d.ts.map +1 -1
- package/dist/components/resources/ResourceCell.js +5 -19
- package/dist/components/resources/ResourceTable.d.ts +5 -2
- package/dist/components/resources/ResourceTable.d.ts.map +1 -1
- package/dist/components/resources/ResourceTable.js +54 -5
- package/dist/hooks/useVertebrControls.d.ts.map +1 -1
- package/dist/hooks/useVertebrControls.js +5 -4
- package/dist/index.d.ts +7 -2
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +4 -1
- package/dist/lib/description.d.ts +18 -0
- package/dist/lib/description.d.ts.map +1 -0
- package/dist/lib/description.js +85 -0
- package/dist/lib/images.d.ts +14 -0
- package/dist/lib/images.d.ts.map +1 -0
- package/dist/lib/images.js +63 -0
- package/dist/lib/price.d.ts +15 -0
- package/dist/lib/price.d.ts.map +1 -0
- package/dist/lib/price.js +50 -0
- package/dist/styles/form.css +275 -0
- package/dist/styles/modal.css +115 -0
- package/dist/styles/panel.css +12 -1
- package/dist/styles/table.css +10 -1
- package/package.json +9 -2
|
@@ -0,0 +1,63 @@
|
|
|
1
|
+
function looksLikeUrl(value) {
|
|
2
|
+
return /^https?:\/\//i.test(value) || value.startsWith("//");
|
|
3
|
+
}
|
|
4
|
+
export function isImageField(key, field) {
|
|
5
|
+
if (field?.type === "file[]")
|
|
6
|
+
return true;
|
|
7
|
+
const hay = `${key} ${field?.label ?? ""}`;
|
|
8
|
+
return /(image|img|photo|avatar|thumbnail|thumb|cover)/i.test(hay);
|
|
9
|
+
}
|
|
10
|
+
function urlFromUnknown(value) {
|
|
11
|
+
if (typeof value === "string" && looksLikeUrl(value)) {
|
|
12
|
+
return { url: value };
|
|
13
|
+
}
|
|
14
|
+
if (value && typeof value === "object" && "url" in value) {
|
|
15
|
+
const url = value.url;
|
|
16
|
+
const name = value.name;
|
|
17
|
+
if (typeof url === "string" && looksLikeUrl(url)) {
|
|
18
|
+
return {
|
|
19
|
+
url,
|
|
20
|
+
name: typeof name === "string" ? name : undefined,
|
|
21
|
+
};
|
|
22
|
+
}
|
|
23
|
+
}
|
|
24
|
+
return null;
|
|
25
|
+
}
|
|
26
|
+
/** Flatten record image fields (single URL or URL lists) for the editor picker. */
|
|
27
|
+
export function collectRecordImages(schema, values) {
|
|
28
|
+
const images = [];
|
|
29
|
+
for (const [key, field] of Object.entries(schema)) {
|
|
30
|
+
if (!isImageField(key, field))
|
|
31
|
+
continue;
|
|
32
|
+
const label = field.label?.trim() || key;
|
|
33
|
+
const value = values?.[key];
|
|
34
|
+
const items = Array.isArray(value) ? value : [value];
|
|
35
|
+
items.forEach((item, index) => {
|
|
36
|
+
const parsed = urlFromUnknown(item);
|
|
37
|
+
if (!parsed)
|
|
38
|
+
return;
|
|
39
|
+
images.push({
|
|
40
|
+
id: `${key}:${index}`,
|
|
41
|
+
url: parsed.url,
|
|
42
|
+
name: parsed.name || (items.length > 1 ? `${label} ${index + 1}` : label),
|
|
43
|
+
field: key,
|
|
44
|
+
});
|
|
45
|
+
});
|
|
46
|
+
}
|
|
47
|
+
return images;
|
|
48
|
+
}
|
|
49
|
+
export function urlsFromValue(value) {
|
|
50
|
+
const items = Array.isArray(value)
|
|
51
|
+
? value
|
|
52
|
+
: value == null || value === ""
|
|
53
|
+
? []
|
|
54
|
+
: [value];
|
|
55
|
+
const urls = [];
|
|
56
|
+
for (const item of items) {
|
|
57
|
+
const parsed = urlFromUnknown(item);
|
|
58
|
+
if (parsed)
|
|
59
|
+
urls.push(parsed.url);
|
|
60
|
+
}
|
|
61
|
+
return urls;
|
|
62
|
+
}
|
|
63
|
+
export { looksLikeUrl };
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
import type { FieldSchema } from "@vertebr/client";
|
|
2
|
+
export declare function isCentsField(key: string, field?: Pick<FieldSchema, "label">): boolean;
|
|
3
|
+
export declare function isPriceField(key: string, field?: Pick<FieldSchema, "label">): boolean;
|
|
4
|
+
export declare function dollarsFromStored(value: number, asCents: boolean): number;
|
|
5
|
+
export declare function storedFromDollars(dollars: number, asCents: boolean): number;
|
|
6
|
+
/** Format a stored number for display (`3800` cents → `$38.00`). */
|
|
7
|
+
export declare function formatPrice(value: number, options?: {
|
|
8
|
+
asCents?: boolean;
|
|
9
|
+
currency?: string;
|
|
10
|
+
}): string;
|
|
11
|
+
/** Value shown in an editable money input (`3800` → `38.00`). */
|
|
12
|
+
export declare function formatPriceInput(value: unknown, asCents?: boolean): string;
|
|
13
|
+
/** Parse typed money (`$38`, `38.00`, `38`) back to stored units. */
|
|
14
|
+
export declare function parsePriceInput(raw: string, asCents?: boolean): number | undefined;
|
|
15
|
+
//# sourceMappingURL=price.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"price.d.ts","sourceRoot":"","sources":["../../src/lib/price.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,iBAAiB,CAAC;AAKnD,wBAAgB,YAAY,CAC1B,GAAG,EAAE,MAAM,EACX,KAAK,CAAC,EAAE,IAAI,CAAC,WAAW,EAAE,OAAO,CAAC,GACjC,OAAO,CAET;AAED,wBAAgB,YAAY,CAC1B,GAAG,EAAE,MAAM,EACX,KAAK,CAAC,EAAE,IAAI,CAAC,WAAW,EAAE,OAAO,CAAC,GACjC,OAAO,CAGT;AAED,wBAAgB,iBAAiB,CAAC,KAAK,EAAE,MAAM,EAAE,OAAO,EAAE,OAAO,GAAG,MAAM,CAEzE;AAED,wBAAgB,iBAAiB,CAAC,OAAO,EAAE,MAAM,EAAE,OAAO,EAAE,OAAO,GAAG,MAAM,CAE3E;AAED,oEAAoE;AACpE,wBAAgB,WAAW,CACzB,KAAK,EAAE,MAAM,EACb,OAAO,CAAC,EAAE;IAAE,OAAO,CAAC,EAAE,OAAO,CAAC;IAAC,QAAQ,CAAC,EAAE,MAAM,CAAA;CAAE,GACjD,MAAM,CAcR;AAED,iEAAiE;AACjE,wBAAgB,gBAAgB,CAC9B,KAAK,EAAE,OAAO,EACd,OAAO,UAAO,GACb,MAAM,CAGR;AAED,qEAAqE;AACrE,wBAAgB,eAAe,CAC7B,GAAG,EAAE,MAAM,EACX,OAAO,UAAO,GACb,MAAM,GAAG,SAAS,CAQpB"}
|
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
const CENTS_KEY = /(cents|priceCents|amountCents)/i;
|
|
2
|
+
const PRICE_KEY = /(price|amount|cost|total|msrp)/i;
|
|
3
|
+
export function isCentsField(key, field) {
|
|
4
|
+
return CENTS_KEY.test(key) || /cents/i.test(field?.label ?? "");
|
|
5
|
+
}
|
|
6
|
+
export function isPriceField(key, field) {
|
|
7
|
+
if (isCentsField(key, field))
|
|
8
|
+
return true;
|
|
9
|
+
return PRICE_KEY.test(key) || PRICE_KEY.test(field?.label ?? "");
|
|
10
|
+
}
|
|
11
|
+
export function dollarsFromStored(value, asCents) {
|
|
12
|
+
return asCents ? value / 100 : value;
|
|
13
|
+
}
|
|
14
|
+
export function storedFromDollars(dollars, asCents) {
|
|
15
|
+
return asCents ? Math.round(dollars * 100) : dollars;
|
|
16
|
+
}
|
|
17
|
+
/** Format a stored number for display (`3800` cents → `$38.00`). */
|
|
18
|
+
export function formatPrice(value, options) {
|
|
19
|
+
const asCents = options?.asCents ?? true;
|
|
20
|
+
const currency = options?.currency ?? "USD";
|
|
21
|
+
const amount = dollarsFromStored(value, asCents);
|
|
22
|
+
try {
|
|
23
|
+
return new Intl.NumberFormat(undefined, {
|
|
24
|
+
style: "currency",
|
|
25
|
+
currency,
|
|
26
|
+
minimumFractionDigits: 2,
|
|
27
|
+
maximumFractionDigits: 2,
|
|
28
|
+
}).format(amount);
|
|
29
|
+
}
|
|
30
|
+
catch {
|
|
31
|
+
return `$${amount.toFixed(2)}`;
|
|
32
|
+
}
|
|
33
|
+
}
|
|
34
|
+
/** Value shown in an editable money input (`3800` → `38.00`). */
|
|
35
|
+
export function formatPriceInput(value, asCents = true) {
|
|
36
|
+
if (typeof value !== "number" || !Number.isFinite(value))
|
|
37
|
+
return "";
|
|
38
|
+
return dollarsFromStored(value, asCents).toFixed(2);
|
|
39
|
+
}
|
|
40
|
+
/** Parse typed money (`$38`, `38.00`, `38`) back to stored units. */
|
|
41
|
+
export function parsePriceInput(raw, asCents = true) {
|
|
42
|
+
const cleaned = raw.replace(/[^0-9.-]/g, "");
|
|
43
|
+
if (!cleaned || cleaned === "-" || cleaned === "." || cleaned === "-.") {
|
|
44
|
+
return undefined;
|
|
45
|
+
}
|
|
46
|
+
const dollars = Number(cleaned);
|
|
47
|
+
if (!Number.isFinite(dollars))
|
|
48
|
+
return undefined;
|
|
49
|
+
return storedFromDollars(dollars, asCents);
|
|
50
|
+
}
|
package/dist/styles/form.css
CHANGED
|
@@ -234,6 +234,252 @@
|
|
|
234
234
|
padding-top: 0.65rem;
|
|
235
235
|
}
|
|
236
236
|
|
|
237
|
+
.vertebr-field-money {
|
|
238
|
+
display: grid;
|
|
239
|
+
grid-template-columns: auto minmax(0, 1fr);
|
|
240
|
+
align-items: stretch;
|
|
241
|
+
}
|
|
242
|
+
|
|
243
|
+
.vertebr-field-money-prefix {
|
|
244
|
+
display: grid;
|
|
245
|
+
place-items: center;
|
|
246
|
+
padding: 0 0.7rem;
|
|
247
|
+
border: 1px solid var(--vb-border);
|
|
248
|
+
border-right: 0;
|
|
249
|
+
border-radius: var(--vb-radius-sm) 0 0 var(--vb-radius-sm);
|
|
250
|
+
background: var(--vb-surface-tint);
|
|
251
|
+
color: var(--vb-text-muted);
|
|
252
|
+
font-family: var(--vb-mono);
|
|
253
|
+
font-size: 0.86rem;
|
|
254
|
+
}
|
|
255
|
+
|
|
256
|
+
.vertebr-field-money input {
|
|
257
|
+
border-top-left-radius: 0;
|
|
258
|
+
border-bottom-left-radius: 0;
|
|
259
|
+
font-variant-numeric: tabular-nums;
|
|
260
|
+
font-family: var(--vb-mono);
|
|
261
|
+
}
|
|
262
|
+
|
|
263
|
+
.vertebr-field-prose {
|
|
264
|
+
display: grid;
|
|
265
|
+
gap: 0;
|
|
266
|
+
border: 1px solid var(--vb-border);
|
|
267
|
+
border-radius: var(--vb-radius-sm);
|
|
268
|
+
background: var(--vb-bg);
|
|
269
|
+
overflow: hidden;
|
|
270
|
+
}
|
|
271
|
+
|
|
272
|
+
.vertebr-md-toolbar {
|
|
273
|
+
display: flex;
|
|
274
|
+
flex-wrap: wrap;
|
|
275
|
+
align-items: center;
|
|
276
|
+
gap: 0.15rem;
|
|
277
|
+
padding: 0.35rem 0.4rem;
|
|
278
|
+
border-bottom: 1px solid var(--vb-border);
|
|
279
|
+
background: var(--vb-surface-tint);
|
|
280
|
+
}
|
|
281
|
+
|
|
282
|
+
.vertebr-md-btn {
|
|
283
|
+
appearance: none;
|
|
284
|
+
border: 0;
|
|
285
|
+
background: transparent;
|
|
286
|
+
color: var(--vb-text-muted);
|
|
287
|
+
border-radius: 5px;
|
|
288
|
+
min-width: 1.7rem;
|
|
289
|
+
height: 1.7rem;
|
|
290
|
+
padding: 0 0.4rem;
|
|
291
|
+
font: inherit;
|
|
292
|
+
font-size: 0.78rem;
|
|
293
|
+
font-weight: 600;
|
|
294
|
+
cursor: pointer;
|
|
295
|
+
}
|
|
296
|
+
|
|
297
|
+
.vertebr-md-btn:hover:not(:disabled) {
|
|
298
|
+
background: var(--vb-bg-hover);
|
|
299
|
+
color: var(--vb-text);
|
|
300
|
+
}
|
|
301
|
+
|
|
302
|
+
.vertebr-md-btn[data-active="true"] {
|
|
303
|
+
background: var(--vb-bg-hover);
|
|
304
|
+
color: var(--vb-text);
|
|
305
|
+
}
|
|
306
|
+
|
|
307
|
+
.vertebr-md-btn:disabled {
|
|
308
|
+
opacity: 0.45;
|
|
309
|
+
cursor: not-allowed;
|
|
310
|
+
}
|
|
311
|
+
|
|
312
|
+
.vertebr-md-glyph {
|
|
313
|
+
font-weight: 700;
|
|
314
|
+
}
|
|
315
|
+
|
|
316
|
+
.vertebr-md-italic {
|
|
317
|
+
font-style: italic;
|
|
318
|
+
font-family: Georgia, "Times New Roman", serif;
|
|
319
|
+
}
|
|
320
|
+
|
|
321
|
+
.vertebr-md-strike {
|
|
322
|
+
text-decoration: line-through;
|
|
323
|
+
}
|
|
324
|
+
|
|
325
|
+
.vertebr-md-sep {
|
|
326
|
+
width: 1px;
|
|
327
|
+
height: 1rem;
|
|
328
|
+
margin: 0 0.25rem;
|
|
329
|
+
background: var(--vb-border);
|
|
330
|
+
}
|
|
331
|
+
|
|
332
|
+
.vertebr-field-prose textarea,
|
|
333
|
+
.vertebr-md-content {
|
|
334
|
+
resize: none;
|
|
335
|
+
min-height: 7.5rem;
|
|
336
|
+
overflow: hidden;
|
|
337
|
+
line-height: 1.55;
|
|
338
|
+
border: 0;
|
|
339
|
+
border-radius: 0;
|
|
340
|
+
box-shadow: none;
|
|
341
|
+
}
|
|
342
|
+
|
|
343
|
+
.vertebr-md-content {
|
|
344
|
+
padding: 0.65rem 0.75rem;
|
|
345
|
+
outline: none;
|
|
346
|
+
color: var(--vb-text);
|
|
347
|
+
}
|
|
348
|
+
|
|
349
|
+
.vertebr-md-content p {
|
|
350
|
+
margin: 0 0 0.65em;
|
|
351
|
+
}
|
|
352
|
+
|
|
353
|
+
.vertebr-md-content p:last-child {
|
|
354
|
+
margin-bottom: 0;
|
|
355
|
+
}
|
|
356
|
+
|
|
357
|
+
.vertebr-md-content h2,
|
|
358
|
+
.vertebr-md-content h3 {
|
|
359
|
+
margin: 0.85em 0 0.4em;
|
|
360
|
+
font-size: 1.05em;
|
|
361
|
+
font-weight: 650;
|
|
362
|
+
line-height: 1.3;
|
|
363
|
+
}
|
|
364
|
+
|
|
365
|
+
.vertebr-md-content ul,
|
|
366
|
+
.vertebr-md-content ol {
|
|
367
|
+
margin: 0.35em 0 0.65em;
|
|
368
|
+
padding-left: 1.3rem;
|
|
369
|
+
}
|
|
370
|
+
|
|
371
|
+
.vertebr-md-content a {
|
|
372
|
+
color: var(--vb-accent);
|
|
373
|
+
}
|
|
374
|
+
|
|
375
|
+
.vertebr-md-content s {
|
|
376
|
+
text-decoration: line-through;
|
|
377
|
+
}
|
|
378
|
+
|
|
379
|
+
.vertebr-md-content code {
|
|
380
|
+
font-family: var(--vb-mono);
|
|
381
|
+
font-size: 0.86em;
|
|
382
|
+
padding: 0.08em 0.32em;
|
|
383
|
+
border-radius: 4px;
|
|
384
|
+
background: var(--vb-surface-tint);
|
|
385
|
+
border: 1px solid var(--vb-border);
|
|
386
|
+
}
|
|
387
|
+
|
|
388
|
+
.vertebr-md-content pre {
|
|
389
|
+
margin: 0.45em 0 0.7em;
|
|
390
|
+
padding: 0.65rem 0.75rem;
|
|
391
|
+
overflow: auto;
|
|
392
|
+
border-radius: 6px;
|
|
393
|
+
background: var(--vb-surface-tint);
|
|
394
|
+
border: 1px solid var(--vb-border);
|
|
395
|
+
}
|
|
396
|
+
|
|
397
|
+
.vertebr-md-content pre code {
|
|
398
|
+
padding: 0;
|
|
399
|
+
border: 0;
|
|
400
|
+
background: transparent;
|
|
401
|
+
}
|
|
402
|
+
|
|
403
|
+
.vertebr-md-content blockquote {
|
|
404
|
+
margin: 0.45em 0 0.7em;
|
|
405
|
+
padding: 0.15rem 0 0.15rem 0.75rem;
|
|
406
|
+
border-left: 2px solid var(--vb-accent-dim);
|
|
407
|
+
color: var(--vb-text-muted);
|
|
408
|
+
}
|
|
409
|
+
|
|
410
|
+
.vertebr-md-content img {
|
|
411
|
+
display: block;
|
|
412
|
+
max-width: 100%;
|
|
413
|
+
height: auto;
|
|
414
|
+
margin: 0.5em 0;
|
|
415
|
+
border-radius: 8px;
|
|
416
|
+
border: 1px solid var(--vb-border);
|
|
417
|
+
}
|
|
418
|
+
|
|
419
|
+
.vertebr-md-content table {
|
|
420
|
+
width: 100%;
|
|
421
|
+
border-collapse: collapse;
|
|
422
|
+
margin: 0.5em 0 0.75em;
|
|
423
|
+
font-size: 0.88em;
|
|
424
|
+
}
|
|
425
|
+
|
|
426
|
+
.vertebr-md-content th,
|
|
427
|
+
.vertebr-md-content td {
|
|
428
|
+
border: 1px solid var(--vb-border);
|
|
429
|
+
padding: 0.35rem 0.5rem;
|
|
430
|
+
vertical-align: top;
|
|
431
|
+
min-width: 4rem;
|
|
432
|
+
}
|
|
433
|
+
|
|
434
|
+
.vertebr-md-content th {
|
|
435
|
+
background: var(--vb-surface-tint);
|
|
436
|
+
font-weight: 650;
|
|
437
|
+
text-align: left;
|
|
438
|
+
}
|
|
439
|
+
|
|
440
|
+
.vertebr-md-content .selectedCell::after {
|
|
441
|
+
content: "";
|
|
442
|
+
position: absolute;
|
|
443
|
+
inset: 0;
|
|
444
|
+
background: var(--vb-accent-soft);
|
|
445
|
+
pointer-events: none;
|
|
446
|
+
}
|
|
447
|
+
|
|
448
|
+
.vertebr-md-content td,
|
|
449
|
+
.vertebr-md-content th {
|
|
450
|
+
position: relative;
|
|
451
|
+
}
|
|
452
|
+
|
|
453
|
+
.vertebr-md-content p.is-editor-empty:first-child::before {
|
|
454
|
+
color: var(--vb-text-subtle);
|
|
455
|
+
content: attr(data-placeholder);
|
|
456
|
+
float: left;
|
|
457
|
+
height: 0;
|
|
458
|
+
pointer-events: none;
|
|
459
|
+
}
|
|
460
|
+
|
|
461
|
+
.vertebr-field-prose textarea:focus,
|
|
462
|
+
.vertebr-md-content:focus {
|
|
463
|
+
box-shadow: none;
|
|
464
|
+
outline: none;
|
|
465
|
+
}
|
|
466
|
+
|
|
467
|
+
.vertebr-field-prose:focus-within {
|
|
468
|
+
border-color: var(--vb-accent-dim);
|
|
469
|
+
box-shadow: 0 0 0 3px var(--vb-accent-soft);
|
|
470
|
+
}
|
|
471
|
+
|
|
472
|
+
.vertebr-field-prose-meta {
|
|
473
|
+
margin: 0;
|
|
474
|
+
padding: 0.35rem 0.7rem 0.45rem;
|
|
475
|
+
border-top: 1px solid var(--vb-border);
|
|
476
|
+
font-family: var(--vb-mono);
|
|
477
|
+
font-size: 0.68rem;
|
|
478
|
+
letter-spacing: 0.04em;
|
|
479
|
+
color: var(--vb-text-subtle);
|
|
480
|
+
background: var(--vb-surface-tint);
|
|
481
|
+
}
|
|
482
|
+
|
|
237
483
|
.vertebr-field input:hover,
|
|
238
484
|
.vertebr-field textarea:hover {
|
|
239
485
|
border-color: var(--vb-border-strong);
|
|
@@ -269,6 +515,35 @@
|
|
|
269
515
|
background: var(--vb-bg-muted);
|
|
270
516
|
}
|
|
271
517
|
|
|
518
|
+
.vertebr-field-files-list {
|
|
519
|
+
margin: 0;
|
|
520
|
+
padding: 0;
|
|
521
|
+
list-style: none;
|
|
522
|
+
display: grid;
|
|
523
|
+
grid-template-columns: repeat(auto-fill, minmax(92px, 1fr));
|
|
524
|
+
gap: 0.55rem;
|
|
525
|
+
}
|
|
526
|
+
|
|
527
|
+
.vertebr-field-files-list li {
|
|
528
|
+
display: grid;
|
|
529
|
+
gap: 0.35rem;
|
|
530
|
+
}
|
|
531
|
+
|
|
532
|
+
.vertebr-field-files-list img {
|
|
533
|
+
width: 100%;
|
|
534
|
+
aspect-ratio: 1;
|
|
535
|
+
object-fit: cover;
|
|
536
|
+
border-radius: var(--vb-radius);
|
|
537
|
+
border: 1px solid var(--vb-border);
|
|
538
|
+
background: var(--vb-bg-muted);
|
|
539
|
+
}
|
|
540
|
+
|
|
541
|
+
.vertebr-field-files-empty {
|
|
542
|
+
margin: 0;
|
|
543
|
+
font-size: 0.82rem;
|
|
544
|
+
color: var(--vb-text-subtle);
|
|
545
|
+
}
|
|
546
|
+
|
|
272
547
|
.vertebr-field[data-kind="image"] {
|
|
273
548
|
grid-column: 1 / -1;
|
|
274
549
|
}
|
package/dist/styles/modal.css
CHANGED
|
@@ -108,3 +108,118 @@
|
|
|
108
108
|
margin: 0;
|
|
109
109
|
min-width: 0;
|
|
110
110
|
}
|
|
111
|
+
|
|
112
|
+
.vertebr-picker-body {
|
|
113
|
+
gap: 0.95rem;
|
|
114
|
+
}
|
|
115
|
+
|
|
116
|
+
.vertebr-picker-tabs {
|
|
117
|
+
display: flex;
|
|
118
|
+
gap: 0.35rem;
|
|
119
|
+
padding: 0.2rem;
|
|
120
|
+
border: 1px solid var(--vb-border);
|
|
121
|
+
border-radius: 8px;
|
|
122
|
+
background: var(--vb-surface-tint);
|
|
123
|
+
}
|
|
124
|
+
|
|
125
|
+
.vertebr-picker-tabs button {
|
|
126
|
+
appearance: none;
|
|
127
|
+
flex: 1 1 0;
|
|
128
|
+
display: inline-flex;
|
|
129
|
+
align-items: center;
|
|
130
|
+
justify-content: center;
|
|
131
|
+
gap: 0.4rem;
|
|
132
|
+
border: 0;
|
|
133
|
+
background: transparent;
|
|
134
|
+
color: var(--vb-text-muted);
|
|
135
|
+
border-radius: 6px;
|
|
136
|
+
padding: 0.4rem 0.55rem;
|
|
137
|
+
font: inherit;
|
|
138
|
+
font-size: 0.82rem;
|
|
139
|
+
cursor: pointer;
|
|
140
|
+
}
|
|
141
|
+
|
|
142
|
+
.vertebr-picker-tabs button[data-active="true"] {
|
|
143
|
+
background: var(--vb-bg-elevated);
|
|
144
|
+
color: var(--vb-text);
|
|
145
|
+
box-shadow: 0 1px 0 color-mix(in srgb, var(--vb-text) 8%, transparent);
|
|
146
|
+
}
|
|
147
|
+
|
|
148
|
+
.vertebr-picker-tabs span {
|
|
149
|
+
font-family: var(--vb-mono);
|
|
150
|
+
font-size: 0.68rem;
|
|
151
|
+
color: var(--vb-text-subtle);
|
|
152
|
+
}
|
|
153
|
+
|
|
154
|
+
.vertebr-picker-url {
|
|
155
|
+
display: grid;
|
|
156
|
+
grid-template-columns: minmax(0, 1fr) auto;
|
|
157
|
+
gap: 0.5rem;
|
|
158
|
+
}
|
|
159
|
+
|
|
160
|
+
.vertebr-picker-grid {
|
|
161
|
+
display: grid;
|
|
162
|
+
grid-template-columns: repeat(auto-fill, minmax(128px, 1fr));
|
|
163
|
+
gap: 0.7rem;
|
|
164
|
+
}
|
|
165
|
+
|
|
166
|
+
.vertebr-picker-tile {
|
|
167
|
+
appearance: none;
|
|
168
|
+
display: grid;
|
|
169
|
+
gap: 0.4rem;
|
|
170
|
+
padding: 0.45rem;
|
|
171
|
+
border: 1px solid var(--vb-border);
|
|
172
|
+
border-radius: 10px;
|
|
173
|
+
background: var(--vb-bg);
|
|
174
|
+
color: inherit;
|
|
175
|
+
text-align: left;
|
|
176
|
+
cursor: pointer;
|
|
177
|
+
}
|
|
178
|
+
|
|
179
|
+
.vertebr-picker-tile:hover {
|
|
180
|
+
border-color: var(--vb-border-strong);
|
|
181
|
+
}
|
|
182
|
+
|
|
183
|
+
.vertebr-picker-tile[data-selected="true"] {
|
|
184
|
+
border-color: var(--vb-accent-dim);
|
|
185
|
+
box-shadow: 0 0 0 3px var(--vb-accent-soft);
|
|
186
|
+
}
|
|
187
|
+
|
|
188
|
+
.vertebr-picker-thumb {
|
|
189
|
+
display: block;
|
|
190
|
+
aspect-ratio: 1;
|
|
191
|
+
border-radius: 7px;
|
|
192
|
+
overflow: hidden;
|
|
193
|
+
border: 1px solid var(--vb-border);
|
|
194
|
+
background: var(--vb-bg-muted);
|
|
195
|
+
}
|
|
196
|
+
|
|
197
|
+
.vertebr-picker-thumb img {
|
|
198
|
+
display: block;
|
|
199
|
+
width: 100%;
|
|
200
|
+
height: 100%;
|
|
201
|
+
object-fit: cover;
|
|
202
|
+
}
|
|
203
|
+
|
|
204
|
+
.vertebr-picker-name {
|
|
205
|
+
font-size: 0.75rem;
|
|
206
|
+
overflow: hidden;
|
|
207
|
+
text-overflow: ellipsis;
|
|
208
|
+
white-space: nowrap;
|
|
209
|
+
}
|
|
210
|
+
|
|
211
|
+
.vertebr-picker-foot {
|
|
212
|
+
display: flex;
|
|
213
|
+
align-items: center;
|
|
214
|
+
justify-content: space-between;
|
|
215
|
+
gap: 0.75rem;
|
|
216
|
+
padding: 0.85rem 1.25rem 1.05rem;
|
|
217
|
+
border-top: 1px solid var(--vb-border);
|
|
218
|
+
background: var(--vb-surface-tint);
|
|
219
|
+
}
|
|
220
|
+
|
|
221
|
+
.vertebr-picker-count {
|
|
222
|
+
font-family: var(--vb-mono);
|
|
223
|
+
font-size: 0.72rem;
|
|
224
|
+
color: var(--vb-text-subtle);
|
|
225
|
+
}
|
package/dist/styles/panel.css
CHANGED
|
@@ -53,7 +53,7 @@
|
|
|
53
53
|
flex: 0 0 auto;
|
|
54
54
|
display: flex;
|
|
55
55
|
align-items: center;
|
|
56
|
-
justify-content:
|
|
56
|
+
justify-content: space-between;
|
|
57
57
|
gap: 0.5rem;
|
|
58
58
|
padding: 0.55rem 1rem;
|
|
59
59
|
border-bottom: 1px solid var(--vb-border);
|
|
@@ -67,6 +67,17 @@
|
|
|
67
67
|
flex-wrap: wrap;
|
|
68
68
|
}
|
|
69
69
|
|
|
70
|
+
.vertebr-table-scroll-controls {
|
|
71
|
+
display: inline-flex;
|
|
72
|
+
align-items: center;
|
|
73
|
+
gap: 0.15rem;
|
|
74
|
+
margin-left: auto;
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
.vertebr-table-scroll-btn {
|
|
78
|
+
padding: 0.3rem 0.45rem;
|
|
79
|
+
}
|
|
80
|
+
|
|
70
81
|
.vertebr-btn-icon {
|
|
71
82
|
display: inline-flex;
|
|
72
83
|
align-items: center;
|
package/dist/styles/table.css
CHANGED
|
@@ -3,12 +3,16 @@
|
|
|
3
3
|
.vertebr-table-wrap {
|
|
4
4
|
flex: 1 1 auto;
|
|
5
5
|
min-height: 0;
|
|
6
|
+
min-width: 0;
|
|
6
7
|
max-width: 100%;
|
|
7
8
|
overflow: auto;
|
|
9
|
+
overscroll-behavior-inline: contain;
|
|
10
|
+
scrollbar-gutter: stable;
|
|
8
11
|
}
|
|
9
12
|
|
|
10
13
|
.vertebr-table {
|
|
11
|
-
width:
|
|
14
|
+
width: max-content;
|
|
15
|
+
min-width: 100%;
|
|
12
16
|
border-collapse: separate;
|
|
13
17
|
border-spacing: 0;
|
|
14
18
|
font-size: 0.9rem;
|
|
@@ -24,6 +28,11 @@
|
|
|
24
28
|
white-space: nowrap;
|
|
25
29
|
}
|
|
26
30
|
|
|
31
|
+
.vertebr-table th:not(.vertebr-col-actions),
|
|
32
|
+
.vertebr-table td:not(.vertebr-col-actions) {
|
|
33
|
+
min-width: 6.5rem;
|
|
34
|
+
}
|
|
35
|
+
|
|
27
36
|
.vertebr-table th {
|
|
28
37
|
position: sticky;
|
|
29
38
|
top: 0;
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@vertebr/react",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.3.0",
|
|
4
4
|
"description": "Vertebr admin dashboard UI",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "./dist/index.js",
|
|
@@ -36,13 +36,20 @@
|
|
|
36
36
|
"react-dom": "^18.0.0 || ^19.0.0"
|
|
37
37
|
},
|
|
38
38
|
"dependencies": {
|
|
39
|
-
"@vertebr/client": "*",
|
|
40
39
|
"@hookform/resolvers": "^5.2.1",
|
|
41
40
|
"@radix-ui/react-label": "^2.1.7",
|
|
42
41
|
"@radix-ui/react-select": "^2.3.7",
|
|
43
42
|
"@radix-ui/react-separator": "^1.1.7",
|
|
44
43
|
"@radix-ui/react-switch": "^1.2.5",
|
|
45
44
|
"@tanstack/react-table": "^8.21.3",
|
|
45
|
+
"@tiptap/extension-image": "^3.29.2",
|
|
46
|
+
"@tiptap/extension-table": "^3.29.2",
|
|
47
|
+
"@tiptap/extensions": "^3.29.2",
|
|
48
|
+
"@tiptap/markdown": "^3.29.2",
|
|
49
|
+
"@tiptap/pm": "^3.29.2",
|
|
50
|
+
"@tiptap/react": "^3.29.2",
|
|
51
|
+
"@tiptap/starter-kit": "^3.29.2",
|
|
52
|
+
"@vertebr/client": "*",
|
|
46
53
|
"react-hook-form": "^7.62.0",
|
|
47
54
|
"zod": "^3.25.76"
|
|
48
55
|
},
|